Comment(注释)
Go 支持 // 行注释和 /* ... */ 块注释。除了说明实现原因,注释还承担生成包文档、标记 API 弃用状态和承载工具链指令等职责,因此位置和格式有时会影响程序之外的工具行为。
两种注释
package main
import "fmt"
func main() {
// 行注释从 // 开始,到当前行结束。
message := "Hello, Go"
/* 块注释可以写在一行,
也可以跨越多行。 */
fmt.Println(message)
}
块注释不能嵌套。注释标记出现在解释字符串或 rune 字面量内部时,只是普通字符:
package main
import "fmt"
func main() {
fmt.Println("https://go.dev") // 字符串中的 // 不会开始注释
}
短说明通常使用连续的 //,这样更容易增删某一行,也符合 Go 源码中的常见习惯。块注释适合暂时保留较长说明或嵌入式示例,但不应用于长期“注释掉”失效代码;版本控制已经保存历史。
文档注释
紧邻包、常量、变量、函数、类型、字段或方法声明之前的注释可以成为文档注释(doc comment),由 go doc 等 Go 工具读取:
// Package temperature 提供摄氏温度与华氏温度之间的转换。
package temperature
// Celsius 表示摄氏温度。
type Celsius float64
// Fahrenheit 将摄氏温度转换为华氏温度。
func (c Celsius) Fahrenheit() float64 {
return float64(c)*9/5 + 32
}
好的文档注释应遵循以下习惯:
- 包注释以
Package 包名开头,说明包解决什么问题。 - 导出声明的注释以被声明的名称开头,并形成完整句子。
- 说明调用约束、错误、并发安全或副作用,而不是重复函数签名。
- 注释与声明之间不要插入无关声明,以免文档工具无法正确关联。
在模块目录运行以下命令可以查看生成效果:
go doc ./...
具体格式以 Go Doc Comments 为准;工具会按段落、标题、列表、代码块和链接等规则解释注释文本。
并非每个局部变量都需要注释。命名和结构已经能清楚表达“做什么”时,注释应重点解释“为什么这样做”、有哪些非显然约束,以及哪些行为是调用方必须知道的。
包注释
包注释写在 package 子句之前。较短的包说明可以放在任意一个非测试文件中;较长的说明常单独放在 doc.go:
// Package retry 提供带退避策略的有限次数重试。
//
// 调用方应确保传入操作可以安全重试,并为整个重试过程设置截止时间。
package retry
同一个包通常维护一份主要包注释,避免不同文件生成重复或矛盾的概述。
弃用说明
公开 API 不再推荐使用时,可以在文档注释的独立段落中使用 Deprecated: 标记:
// ParseAddress 解析服务地址。
//
// Deprecated: Use ParseEndpoint instead.
func ParseAddress(value string) string {
return value
}
弃用说明应指出替代方案和必要的迁移条件。Deprecated: 是工具可识别的约定,不要用“旧方法”“暂勿使用”等模糊措辞代替。
工具链指令不是普通说明
以 //go: 开头的注释可能是编译器或工具链指令,例如生成命令:
package assets
//go:generate go run ./cmd/generate
这类指令对位置和空格有严格要求,只有执行相应工具时才产生效果。例如 go generate ./... 会处理 //go:generate,普通构建不会自动运行生成命令。
不要为了视觉统一修改未知的 //go: 指令,也不要在普通说明中随意使用此前缀。修改前应查询对应工具的正式文档。
注释应记录什么
适合写入注释的内容包括:
- 业务规则背后的原因和外部约束。
- 看似可以简化、实际必须保留的兼容处理。
- 公开 API 的错误、资源所有权和并发安全约定。
- 临时方案的移除条件,并配合可追踪的任务编号。
下面的注释只是在重复代码,应优先删除:
// count 加一。
count++
下面的注释解释了非显然原因,具有维护价值:
// 上游按自然日结算,因此这里必须使用业务时区,不能直接按 UTC 截断。
settlementDate := now.In(businessLocation).Format("2006-01-02")
与 TypeScript 的区别
两种语言都支持 // 和 /* ... */,也都能从注释生成 API 文档。不过 Go 的文档工具偏好紧邻声明、以声明名称开头的自然语言注释;Go 还使用 //go: 承载工具链指令。不要把 JSDoc 的 @param、@returns 模板机械搬到 Go,参数与返回类型已经由函数签名表达。
小结
//用于行注释,/* ... */用于块注释,块注释不能嵌套。- 文档注释应紧邻声明,导出名称的说明通常以该名称开头。
- 包注释说明整个包的职责,较长内容可以放在
doc.go。 Deprecated:是工具可识别的弃用标记,应同时给出替代方案。//go:可能影响工具链行为,必须按对应指令的正式规则维护。