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 // 错误
相关文章
相关标签/搜索