Go語言知識點四十二章經

  1. 內存分配發生在運行時,編譯後的機器碼不使用變量名而是直接使用內存地址訪問目標數據,所以編碼階段採用易於閱讀的變量名
  2. 慣例建議以組的方式整理多行變量定義 var {x,y int } type{ xxx }
  3. 簡短聲明一般用於函數多返回值,以及if for switch等語句中定義局部變量
  4. 未使用的局部變量會編譯出錯,全局變量不報錯
  5. 常量實在預處理階段展開成指令數據,變量是在運行期分配存儲內存.(所以常量無法尋址,沒有地址)
  6. byte是uint8的別名 rune是int32的別名 別名直接可以相互賦值不需要類型轉換;擁有相同的底層結構不代表就屬於別名
  7. 未命名類型:數組、切片、字典、通道等類型與具體元素類型或長度等屬性相關的類型,可以用type將其改變成命名類型;對於未命名類型 struct tag不同也屬於不同類型,字段順序不同也屬於不同類型
  8. 自增自減只能作爲獨立語句
  9. .range迭代是複製數據
  10. goto只能跳轉到同級代碼,不能跨級別
  11. break用於switch for select,終止整個語句塊執行;continue只用於for循環,終止後續邏輯立即進入下一輪循環
  12. 函數類型只支持nil判斷,不支持其他比較操作
  13. 從函數返回局部變量指針是安全的,編譯器會通過逃逸分析來決定是否在堆上分配內存;所以參數儘量減少值拷貝
  14. 不管是指針、引用類型還是其它類型參數,都是值拷貝傳遞,區別在於拷貝的目標對象
  15. 指針傳遞壞處在於延長該變量的聲明週期,也可能導致他分配到堆上增加性能消耗
  16. 變參 func test(a …int){} test(a[:]…)
  17. 命名返回值的問題: 新定義的同名局部變量會引起同名遮蔽:xx is shadowed during return ;此時實名return即可
  18. error是接口類型
  19. runtime/debug.PrintStrack()可以打印完整的堆棧信息
  20. 多個panic僅最後一個被捕獲;不可恢復性、導致系統無法正常工作的錯誤纔會使用panic (文件系統沒權限操作、服務端口被佔用、數據庫未啓動等)
  21. 字符串是不可變字節(byte)序列,可用len獲取長度,不可用cap;
  22. range遍歷可以打印出漢字,len遍歷出的漢字是亂碼;utf8.RuneCountInString(s)代替len獲取帶漢字的字符串長度
  23. 字符串加法運算每次都會重新分配內存,構建大字符串性能極差;方法1:strings.Join 方法2:bytes.Buffer 小字符串拼接使用fmt.Sprintf text/template等
  24. 長度是數組的類型組成部分,元素類型相同長度不同的數組不是同一類型
  25. 切片:不是動態數組或數組指針;內部通過指針引用底層數組,設定相關屬性將數據讀寫操作限定在指定區域內。可以理解爲數組指針的包裝
  26. 切片 var a[]int 爲nil,僅代表他未初始化,但依舊分配內存;且a[:]依舊是nil
  27. 可將字符串直接複製到[]byte => b:=make([]byte,3) n:=copy(b,“abcdefhg”)=>n=3,b=[97 98 99]
  28. 切片初始化多大cap,copy就會複製成功<=cap的數據
  29. 字典的key必須支持== != 如數字、字符串、指針、數組、結構、接口
  30. if v,ok:=m[“d”];ok{存在} 使用ok-idiom模式判斷key是否存在
  31. delete(m,“d”),刪除不存在的key不報錯
  32. map被設計成 no addressable,所有沒法修改value的成員(如果value是個結構或者數組等) ;改進方法1:先獲取完整value,修改後再賦值回去;方法2:value採用指針類型。因爲value是指針,所有可以通過指針修改指針指向的數據。
  33. 對於海量小對象,應該直接用字典存儲鍵值數據拷貝而不是指針,這樣減少掃描對象的數量縮短垃圾回收時間。
  34. 字典不會收縮內存,適當替換新對象是有必要的
  35. 字段標籤是對字段描述的元數據,是類型的組成部分;運行期間可用反射獲取標籤信息,通常作爲格式校驗和數據庫關係映射等
  36. reflect.StructTag提供了更完善的功能
  37. T的方法集是 receiver T;*T的方法集是receiver T+*T
  38. 匿名嵌入S,T包含 receiver S;匿名嵌入*S,T包含 receiver S+S; 匿名嵌入S或S,*T都包含 receiver S+*S;
  39. 方法集僅影響接口實現和方法表達式轉換。匿名字段就是爲方法集準備的
  40. Chan: 一次性事件使用chan的close效率更高 向close的chan發數據panic 從已關閉的chan接收數據返回已緩存數據或零值 無論收發,nil通道都會阻塞
  41. Chan和鎖的選擇: 同步問題應該用鎖或原子變量來操作 對性能要求較高時,應避免使用defer unlock 讀寫併發時,用RWMutex性能更好 對單個數據的讀寫保護建議使用讀寫鎖 嚴格測試,儘可能打開數據競爭檢查 通道傾向於解決邏輯層次的併發處理架構 鎖用來保護局部範圍內的數據安全
  42. 如果對map的讀操作遠遠多於寫操作(寫操作包括新增和刪除key),那麼sync.Map是很合適,能夠大大提升性能

補充
我們在遇到函數沒有實現,但彙編又不存在時,可以通過嘗試搜索:go:linkname xxx xx.xxx的形式來找,比如time.Sleep就可以通過//go:linkname timeSleep time.Sleep來查找具體實現在哪。

定時任務
https://github.com/robfig/cron
https://github.com/jasonlvhit/gocron

IM
https://github.com/GoBelieveIO/im_service

使用 Golang 解析 JSON 格式數據時,若以 interface{} 接收數據,則會按照下列規則進行解析:

bool, for JSON booleans
float64, for JSON numbers
string, for JSON strings
[]interface{}, for JSON arrays
map[string]interface{}, for JSON objects
nil for JSON null

import 後面跟着包路徑
除非特別指定,否則無法使用 nil 對變量賦值
golang 中的類型比如:channel(通道)、complex(複數類型)、func(函數)均不能進行 JSON 格式化。

全局變量遇到簡短聲明

//varTest declared and not used
var varTest string
func test(){
	varTest, err := function()
	fmt.Println(err.Error())
}
func function()(string, error){
	return "hello world", errors.New("error")
}
func main(){
	test()
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章