Go編程容易忽略的問題(持續更新)

  1. slice 切片的初始值是 nil,比如 var s []int s的值爲nil,但任然可以直接使用,而不需要 make 等初始化,對其使用len結果爲0,也可以直接append

  2. 使用 make 對切片初始化的時候,make(Type[], l, c) 使用3個參數時候,l 爲 Len,c 爲 Cap,Len其實是當前切片的一個偏移量,表示現在存儲的有用數據有多少,也可以表示下次 append 的切片下標

  3. 反射中的 reflect.Type 的 Field相關指的是該類型下的導出字段,同樣的 Method 相關的也是導出方法,這點容易忽略

  4. json.Unmarshal(data []byte, v interface{}) 函數,如果入參 v 爲nil 的 interface{} 類型,則內部會爲其分配一個map

  5. 在json序列化的時候,如果該字段的tag爲 json:", omitempty" 則在該字段爲相應0值的時候,去掉該key,也就是序列化的結果不包含該key

  6. 當自定義類型的底層爲基礎類型(int float32等)時,反射打印其類型 Kind() 方法的結果,任然是其底層的類型; 如果使用 interface 裝載該類型,則斷言時候,必須斷言你定義的那個類型,而不能斷言爲底層類型,因爲類型畢竟還是不一樣,只是底層相同而已,可以看下如下代碼

type A int
var b interface{} = A(1)
tb := reflect.TypeOf(b)
fmt.Println(tb.Kind())
// out: int

bb := b.(int) // panic
  1. 內嵌是go實現oop思想的一個辦法,外部類型自動獲得內嵌類型的副本(成員和方法)

  2. bufio 使用完,記得一定要調用 Flush 函數把剩餘緩存數據刷出去,因爲在緩存範圍內,是不會執行io操作的

  3. 使用 go module 之後,項目不再受限於 GOPATH,可以任意放置,但是初始化項目時候需要給出包名 比如像這樣 go mod init github.com/Name/Project

  4. 切片拷貝

var s1 []int{0, 0}
s2 := s1 
// 淺拷貝
// 這樣就完成了拷貝,但是數組還是同一個,如果以 append 對 s2 進行增量操作,則對s1無影響,如果通過下標修改s2的值,則s1也會跟着修改
// s1(Len, Cap) --> 數組 <--s2(Len, Cap)
// 參考go源碼: src/reflect/value.go SliceHeader

// 拷貝底層數組
s1 := []int{1, 2}
s2 := make([]int, len(s1)) // 注意必須使 s2 的 Len >= len(s1)
copy(s2, s1) // 拷貝s1中的值到s2
fmt.Println(s2)

// 追加方式拷貝
s1 := []int{1, 2}
s2 := make([]int, 0, 2)
s2 = append(s2, s1...)

// 以上幾種都不能解決在 s1 爲 nil的情況(此時拷貝對象結果應該也爲nil才符合預期)
// 下面是目前最好的方案
s1 := []int{1, 2}
s2 := make([]int, 0, 2)
s2 = append(s1[:0:0], s1...)
  1. bufio 包定義了一個帶緩衝的 io,在緩衝範圍內,不會執行io操作,可以用於文件io和網絡io,裏面有個Scanner 很方便地讀取文件,或者字符串到內存,裏面定義了一系列內置的函數(策略模式),可以選擇以何種方式讀取到緩衝(按空格,換行等等)

  2. stringsbytes 包的api幾乎是一樣的,定義了一些,包含,替換,以及比較操作,一個是針對 string 類型,一個是針對 []byte 類型,好在這兩種類型互相轉換非常方便————直接強轉就行;strings 包多了一個 Builder 類型,方便對字符串進行修改操作。

  3. 反引號創建的字符串,叫做 raw string, 所有在在這裏面的字符都會原樣輸出,不支持轉義(動詞)字符,比如下面這個代碼

s := `xxx\nyyy`
fmt.Println(s) // output: xxx\nyyy
  1. 字符串在go當中,是一個以utf-8編碼的只讀 byte 切片;可以通過遍歷獲得 rune(utf-8字符編碼的字符的int值) 並打印,比如下面代碼
s := `ab哈哈看看`
for i, c := range s {
	fmt.Printf("字符:%c 在s序列中的起始index是 %d\n", c, i)
}

// output:
//字符:a 在s序列中的起始index是 0
//字符:b 在s序列中的起始index是 1
//字符:哈 在s序列中的起始index是 2
//字符:哈 在s序列中的起始index是 5
//字符:看 在s序列中的起始index是 8
//字符:看 在s序列中的起始index是 11

可以看到,漢字在utf-8中通常都是佔用3個字節的

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章