Go注释须规范以支持工具链:函数首行注释必须以“函数名+空格”开头;包注释仅顶部一段有效;类型注释重语义轻字段;行内注释只解释“为什么”;名称拼写须与代码完全一致。

Go 语言的注释不是“怎么好看怎么写”,而是直接参与文档生成和工具链解析——go doc、go vet、IDE 跳转、甚至 go test -cover 的覆盖率统计都依赖它。不规范的注释会导致文档缺失、误报警告、协作者读不懂接口意图。
函数/方法必须用首行 Doc 注释,且以函数名开头
Go 工具链(尤其是 godoc 和 VS Code 的 hover 提示)只识别以「函数名 + 空格」起始的首行注释。写成 // 处理用户登录 或 // Login handler 都不会被识别为该函数的文档。
正确写法是:
// Login handles user login request.
// It validates credentials and returns a session token.
// Returns ErrInvalidCredentials if username/password mismatch.
func Login(w http.ResponseWriter, r *http.Request) error {
// ...
}
- 首行必须是
// 函数名开头(注意空格),不能缩写、不能加“Func”“Method”等后缀 - 后续行用完整句子描述行为、参数隐含逻辑、返回值含义,不要写“本函数用于……”这种冗余表达
- 如果函数返回错误,建议明确列出可能的自定义错误变量(如
ErrNotFound),方便调用方errors.Is(err, ErrNotFound)
包注释必须放在 package 声明前,且只能有一段
一个包里多个 // Package xxx 注释会被 go doc 忽略,只有最顶部、紧邻 package 声明前的那一段才会生效。
立即学习“go语言免费学习笔记(深入)”;
错误示例(两个包注释,后者失效):
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
// Package auth provides JWT-based authentication. package auth // Package auth is deprecated. Use v2 instead. ← 这行不会出现在文档中 import "crypto/rand"
正确写法(仅一处,且位置严格):
// Package auth implements JWT-based authentication and session management. // It supports token signing, verification, refresh, and role-based claims. package auth
- 包注释必须是纯文本段落,不能夹带
func或type定义说明——那些属于具体符号的 Doc 注释 - 避免使用“本包”“该模块”这类指代词,直接说功能;读者看的是文档,不是源码上下文
- 如果包很小(比如只有 1–2 个导出符号),包注释可以简短,但不能省略
导出类型(struct / interface)的注释要说明“它代表什么”,而不是“它有哪些字段”
很多人给 type User struct 写一堆字段注释,却漏掉最关键的语义说明:“这个 User 是数据库持久化实体?还是 API 响应 DTO?是否可并发读写?”
正确注释应先回答“是什么”,再补充关键约束:
// User represents a registered end-user in the system.
// It is safe for concurrent read access, but mutations require external locking.
type User struct {
ID int64 `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
}
- 字段注释(
// Name is the display name)可选,但仅当字段名本身不清晰时才加;Name、Email这类无需解释 - interface 注释必须说明契约:实现该接口的类型“必须保证什么行为”,例如
// Writer must not modify the input slice - 不要在类型注释里写初始化示例或用法代码——那是 example_test.go 的事
行内注释只解释“为什么”,不重复“做什么”
// i++ ← 这是废话 比 // retry on transient failure ← 这才是有效信息 更常见。Go 编译器不看行内注释,但它直接影响维护者能否快速理解意图。
- 优先解释魔数、绕过检查的原因、规避的竞态条件、临时 hack 的限制条件
- 避免在
if err != nil后写// check error,而应写// ignore EOF when reading trailer - 长表达式中间加注释容易破坏可读性,不如提成有语义的变量:
isLegacyPath := strings.HasPrefix(path, "/v1/")比strings.HasPrefix(path, "/v1/") // legacy prefix更清晰
最常被忽略的一点:注释里的类型名、函数名、错误变量名,必须和代码中拼写完全一致(包括大小写和包名前缀),否则 go doc 不会自动链接跳转——比如写了 ErrNotFound 但实际定义是 auth.ErrNotFound,链接就断了。

















