golang 學習過程當中踩的坑

[他人總結]

https://chai2010.cn/advanced-go-programming-book/appendix/appendix-a-trap.html
http://km.oa.com/group/16106/articles/show/304264sql

首字母大寫纔是對外可見的

須要首字母大寫纔是對外可見的, 這是的對外指的是不一樣的 package, 特別須要注意的是 json 解析時的 struct 裏面的字段名首字母必須大寫, 不然沒法解析, 同理還有 toml 配置解析等等json

包的初始化函數順序問題

包內的 init() 函數會在 import 包的時候就執行
執行順序:app

  1. 若是一個包的多個文件裏面都有 init 函數, 按文件名排序以後的執行
  2. 同一個文件 import 了多個包, 則按照 import 的前後順序執行
  3. 被遞歸 import 的包的初始化順序與 import 順序相反,例如:導入順序 main –> A –> B –> C,則初始化順序爲 C –> B –> A –> main
  4. 一個包被其它多個包 import,但只能被初始化一次
  5. main 包老是被最後一個初始化
  6. 避免出現循環依賴, 例如:A –> B –> C –> A

DB 鏈接泄漏問題

sql.Open 和 DB.Close 並不能保證鏈接不泄漏, database/sql 實際上是鏈接池, Open 以後並不立刻進行鏈接, 只有實際查詢的時候才發起鏈接.
Query 返回的 Rows 必須 Next 每一行數據纔會斷開鏈接, 以後把鏈接歸還到鏈接池, 沒有讀完的數據比較手動 Rows.Close 才能保證鏈接不泄露.函數

err 經常使用寫法

// 建議都這麼寫:
v, err := doSth()
if err != nil {
    // 出錯了
    ...
}
// 正常的邏輯
...

// 不建議下面這樣寫
// 緣由是 **__err==nil__** 很容易被誤寫成 **__err!=nil__**:
if v, err := doSth(); err == nil {
    // 正常的邏輯
    ...
} else {
    // 出錯了
    ...
}

goroutine 內的變量

// 錯誤
    for i:=0; i < 100; i++ {
        go func() {
            fmt.Println(i)
        }()
    }
    
    // 正確
    for i:=0; i < 100; i++ {
        go func(i int) {
            fmt.Println(i)
        }(i)
    }
    
    // 正確
    for i:=0; i < 100; i++ {
        i := i
        go func() {
            fmt.Println(i)
        }()
    }

指針多是 nil

須要注意返回指針的函數調用者必定要判斷指針是否爲 nil
或者寫帶指針返回值的函數時加一個 error 或者 bool 出參, 這樣調用方不得不判斷是否邏輯異常, 能夠必定程度避免調用方不檢查的狀況指針

多層 map 未初始化

對未初始化的 map 取值正常, 賦值出錯code

var m map[int]int
if m[5] == 5 { // 正確
...
}

m[5] = 5 // 錯誤
m := make(map[int]map[int]int)
m[5][5] = 5 // 錯誤
相關文章
相關標籤/搜索