最佳实践
字数
522 字
阅读时间
3 分钟
GoRoutine 生命周期
- Goroutine 生命周期:明确 Goroutine 退出条件,使用
context.Context管理取消信号。避免因阻塞通道导致泄漏或数据竞争。gofunc (w *Worker) Run(ctx context.Context) error { var wg sync.WaitGroup go func() { defer wg.Done() process(ctx, item) // 随 ctx 取消而终止 }() wg.Wait() }
Contexts 使用
- 显式传递:
context.Context用于传递安全凭证、追踪信息、截止时间和取消信号,应作为函数的第一个参数,贯穿调用链(从 RPC/HTTP 入口到下游请求)。gofunc F(ctx context.Context, otherArgs ...) {} - 避免结构体嵌入:不在结构体中包含
Context字段,而是作为方法参数传递(除非必须实现第三方接口)。 - 不可变性:
Context一旦创建不可修改,可安全传递给多个调用。
复制(Copying)
- 避免别名问题:复制其他包的结构体时(如
bytes.Buffer),注意切片引用,复制后可能共享底层数组。 - 指针接收者:若方法接收者是指针类型(如
*T),避免复制值类型T。
加密随机数(Crypto Rand)
- 禁止使用
math/rand:其默认种子熵不足,无法生成安全随机数(如密钥)。 - 推荐
crypto/rand:使用rand.Read()生成加密安全的随机字节,按需编码为十六进制或 Base64。gofunc Key() string { buf := make([]byte, 16) rand.Read(buf) // 安全的随机数生成 return fmt.Sprintf("%x", buf) }
空切片声明
- 首选
nil切片:go而非var t []string // nil 切片,len 和 cap 均为 0t := []string{}(非 nil 但零长度)。 - 特殊场景:JSON 编码时,
nil切片编码为null,非 nil 零长度切片编码为[],按需选择。
下划线空标识符的使用
- 暂时debug 的原因保留不使用的变量。
go
var _ = fmt.Printf- 接口实现检查
go
var _ io.Reader = (*MyReader)(nil)