首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >10 条写好 Go 的硬核准则(来自 Reddit 工程师在 GoLab 2025 的代码评审笔记)

10 条写好 Go 的硬核准则(来自 Reddit 工程师在 GoLab 2025 的代码评审笔记)

作者头像
萝卜要努力
发布2025-11-14 13:04:03
发布2025-11-14 13:04:03
860
举报
文章被收录于专栏:萝卜要加油萝卜要加油

1) 错误要处理到位,别“吃掉”

  • 不要用 _ = err 或直接忽略。
  • 处理错误时,要么记录日志,要么返回给调用方避免“双重上报”
  • 为调用者优化返回:
    • return result, nil(可用)
    • return nil, err(不可用)
    • return nil, nil(语义暧昧)
    • return result, err(信谁?)
代码语言:javascript
复制
res, err := svc.Do(ctx)
if err != nil { 
    // 选一种:记录 或 返回
    return nil, fmt.Errorf("do: %w", err)
}
return res, nil

2) 别太早上接口(Premature Abstraction)

  • 先用具体类型实现;当确实需要多实现可替换时再引入接口。
  • 遵循惯例:入参接接口,出参返具体
  • 不要为了测试而造接口;优先用真实实现做测试。 (Speaker Deck[1])
代码语言:javascript
复制
// ✅ 起步:具体类型
type FileStore struct{ dir string }
func (s *FileStore) Save(b []byte) error { /*...*/ return nil }

// ✅ 需要多实现时再定义接口
type Saver interface{ Save([]byte) error }
func Upload(s Saver, b []byte) error { return s.Save(b) }

3) 先 Mutex,后 Channel

  • 并发从同步写法开始;确有瓶颈再并发化。
  • 共享状态优先 sync.Mutex / sync.WaitGroup复杂编排再用 channel,减少“二次 close / send on closed”与死锁风险。 (Speaker Deck[2])
代码语言:javascript
复制
type Counter struct {
    mu sync.Mutex
    n  int
}
func (c *Counter) Inc() { c.mu.Lock(); c.n++; c.mu.Unlock() }

4) 就近声明,缩小作用域

  • 常量、变量、类型都在用得到的最近文件/作用域声明。
  • 函数内变量尽量靠近使用处,减少 shadowing 与重构成本。
代码语言:javascript
复制
if ok := check(id); !ok { return errors.New("bad id") } // ok 就地声明

5) 避免运行期 panic

  • 对外部输入(请求、存储、反序列化等)先校验
  • 解引用前判空;更好的是用值类型消除指针解引用
  • 在可控路径下,信任 Go 的 error 处理,不要遍地 if x==nil
代码语言:javascript
复制
type Profile struct {
    Name string // 值类型更安全
}

6) 减少缩进,尽早返回

  • 把错误和否定条件前置返回,让主路径更“平”。
代码语言:javascript
复制
if err := validate(req); err != nil { return err }
// 主流程更扁平

7) 拒绝“大杂烩”包与文件

  • 避免 util.go / misc.go / constants.go 这类“杂物间”。
  • 以领域命名、按意义分组,把代码放到“影响它的附近”。 (Speaker Deck[3])

8) 按重要性排序声明

  • 对外暴露的 API / 入口函数放前面,实现细节与 helper 其后。
  • 让读者先看到“能用起来的东西”,再看“怎么实现的”。 (Speaker Deck[4])

9) 命名靠语义,不靠类型

  • 避免后缀:userMapidStrinjectFn
  • 变量名与作用域大小匹配:作用域越大,命名越要清晰具体。 (Speaker Deck[5])

10) 注释写“为什么”,别复读“做了什么”

  • 解释动机与取舍,而不是翻译源码。
  • 未来的读者通常看得懂“代码做了什么”,却常常不懂“为何如此”。 (Speaker Deck[6])
代码语言:javascript
复制
// 为了避免在热路径上分配,我们用对象池复用缓冲区,牺牲可读性换吞吐。

团队落地的「一页纸」清单

  • 错误:单路径上报;返回值语义清晰,无 nil,nil
  • 抽象:具体起步,入参接口/出参具体,拒绝“为测而测”。
  • 并发:先同步→有瓶颈再并发;共享状态用 Mutex/WG
  • 作用域:就近声明,小作用域小变量名。
  • 安全:外部输入先校验,值类型优于指针
  • 结构:早返回,减少缩进。
  • 组织:拒绝 util.go按领域命名、就近放置。
  • 排序:API 在前,细节在后
  • 命名:语义优先,作用域越大越具体。
  • 注释:写为什么与取舍背景。

参考与延伸

  • GoLab 2025 议程与讲者页(含演讲信息与时间) (golab.io[7])
  • 演讲条目页:Writing Better Go: Lessons from 10 Code Reviews(官方) (golab.io[8])
  • Slides:Speaker Deck(最新要点与示例) (Speaker Deck[9])
  • 收录与讨论:Golang Weekly #575、r/golang 贴文 (golangweekly.com[10])

注:本文为演讲要点的中文化与工程落地版,便于团队直接纳入代码评审与编码规范。欢迎转给同事做 code review checklist。

引用链接

[1]Speaker Deck: https://speakerdeck.com/konradreiche/writing-better-go-lessons-from-10-code-reviews?utm_source=chatgpt.com

[2]Speaker Deck: https://speakerdeck.com/konradreiche/writing-better-go-lessons-from-10-code-reviews?utm_source=chatgpt.com

[3]Speaker Deck: https://speakerdeck.com/konradreiche/writing-better-go-lessons-from-10-code-reviews?utm_source=chatgpt.com

[4]Speaker Deck: https://speakerdeck.com/konradreiche/writing-better-go-lessons-from-10-code-reviews?utm_source=chatgpt.com

[5]Speaker Deck: https://speakerdeck.com/konradreiche/writing-better-go-lessons-from-10-code-reviews?utm_source=chatgpt.com

[6]Speaker Deck: https://speakerdeck.com/konradreiche/writing-better-go-lessons-from-10-code-reviews?utm_source=chatgpt.com

[7]golab.io: https://golab.io/speakers/reiche?utm_source=chatgpt.com

[8]golab.io: https://golab.io/talks/writing-better-go-lessons-from-10-code-reviews?utm_source=chatgpt.com

[9]Speaker Deck: https://speakerdeck.com/konradreiche/writing-better-go-lessons-from-10-code-reviews?utm_source=chatgpt.com

[10]golangweekly.com: https://golangweekly.com/issues/575?utm_source=chatgpt.com

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-10-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 萝卜要加油 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1) 错误要处理到位,别“吃掉”
  • 2) 别太早上接口(Premature Abstraction)
  • 3) 先 Mutex,后 Channel
  • 4) 就近声明,缩小作用域
  • 5) 避免运行期 panic
  • 6) 减少缩进,尽早返回
  • 7) 拒绝“大杂烩”包与文件
  • 8) 按重要性排序声明
  • 9) 命名靠语义,不靠类型
  • 10) 注释写“为什么”,别复读“做了什么”
  • 团队落地的「一页纸」清单
  • 参考与延伸
    • 引用链接
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档