1. 使用 time.Parse()解析时间
导致获取的时间戳比真实的多 8 小时。即使设置了全局的time.Local
也一样,更换成time.ParseInLocation
即可,原因:
go
func Parse(layout, value string) (Time, error) {
// Optimize for RFC3339 as it accounts for over half of all representations.
if layout == RFC3339 || layout == RFC3339Nano {
if t, ok := parseRFC3339(value, Local); ok {
return t, nil
}
}
// 源码中写死的UTC时区
return parse(layout, value, UTC, Local)
}
2. 不清楚 defer 参数是被立即计算的
go
func Doing() error {
var err error
defer handlerErr(err) // handlerErr 永远得到的err是nil
err = doSomething()
return err
}
3. 循环中 defer
go
func Doing() {
mutex := sync.Mutex{}
for i := 0; i < 1000000000; i++ {
mutex.Lock()
defer mutex.Unlock() // 死锁,因为要等方法结束后才Unlock
// do something
}
}
4. 未注意 net/http 中 ctx 生命周期
go
package main
import (
"context"
"net/http"
)
func main() {
http.HandleFunc("/createOrder", func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
// 创建订单
orderDo := createOrder(ctx, reqParams)
// 异步推送订单到供应链
go SubmitToSupplier(ctx, orderDo)
})
http.ListenAndServe(":8080", nil)
}
由于 ctx 在 socket 连接读取出错或 handleFunc 完成时会被 cancel,导致:
- 当浏览器或调用方的 clinet 主动关闭时,即使 createOrder 未运行完,ctx 也会收到 cancel 事件,如是里面有 DB 不在一个事务、或支持 ctx 的 IO 请求的操作,都会中断。
- 协程启动后,由于 handleFunc 运行结束,ctx 被 cancel,导致程序受协程方法运行受影响
5. 协程中未捕获 panic
导致主程序退出,建议统一封装启动协程方法,否则很容易忘记 recover panic