Go 代码审查:检查什么以及如何在实际中提供反馈

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

引言:为什么 Go 中的代码审查不仅仅是一个勾选框

代码审查不是官僚程序,而是开发文化的关键要素。在 Go 中,凭借其简洁的语法和严格的规则,审查常常成为早期过滤问题的第一道防线。许多转向 Golang 的团队发现,旧习惯(例如来自 Python 或 PHP 的习惯)不再适用:Go 对类型相关错误的容忍度更低,但要求关注细节。

在实践中,Go 中的代码审查解决三个任务:团队学习(新手更快融入代码风格),提高质量(发现错误和反模式)和代码一致性(确保项目不会变成“拼凑物”)。让我们具体分析一下要看什么以及如何表述意见。



1. 首先检查什么:从语法到错误

任何审查都从基础开始。Go 中有几个“热点”值得自动或手动检查。



1.1. 错误处理

Go 不使用异常——错误作为值返回。常见问题:开发者使用 _ 忽略返回的错误。这仅在极少数情况下允许(例如 fmt.Println)。

// 不好:错误被忽略resp, _ := http.Get("https://api.example.com/data")

// 好:错误被处理resp, err := http.Get("https://api.example.com/data")if err != nil { log.Printf("无法获取数据:%v", err) return err}defer resp.Body.Close()

检查什么:

  • 所有错误是否都已处理(不仅仅是 _)?
  • 是否使用 defer 关闭资源(文件、连接)?
  • goroutine 中的错误是否被“吞掉”?


1.2. 命名和风格(Go 惯用法)

Go 要求简洁:私有使用 camelCase,导出使用 PascalCase。避免“匈牙利命名法”和长名称。

// 不好func GetUserDataFromDatabase(userID int) (*UserData, error)

// 好func GetUser(id int) (*User, error)

危险信号:

  • 变量名如 temp、data、val(过于通用)。
  • 函数超过 30-40 行(需要拆分)。
  • 导出函数缺少注释(这是 golint 的要求)。


1.3. Goroutine 和同步

这是最复杂的部分。并发代码中的错误是生产环境中常见的错误来源。

// 不好:数据竞争var counter intfor i := 0; i < 100; i++ {    go func() {        counter++ // 不安全    }()}

// 好:使用互斥锁var mu sync.Mutexvar counter intfor i := 0; i < 100; i++ { go func() { mu.Lock() counter++ mu.Unlock() }()}

检查什么:

  • 共享数据是否有 sync.Mutex 或 atomic?
  • 是否忘记关闭通道(close(ch))?
  • goroutine 是否泄漏(没有带超时的 select)?


2. 架构检查:从接口到包

在基础语法之后,查看代码结构。Go 鼓励组合而非继承。



2.1. 接口:小而消费者侧

在 Go 中,接口是隐式实现的。好的接口包含 1-3 个方法。检查作者是否试图创建“包罗万象”的接口。

// 不好:巨大的接口type Storage interface {    Save(data []byte) error    Load(id string) ([]byte, error)    Delete(id string) error    List() ([]string, error)    Connect() error\                

博客

书籍推荐