Go Wiki: 注释
Go 支持 C 风格的 /* */
块注释和 C++ 风格的 //
行注释。行注释是常用方式。
文档注释
包和导出的名称应该有文档注释。文档注释遵循特定的约定并支持简单的格式化语法。更多信息请参阅 Go 文档注释。
指令
某些工具,包括 go 工具和 编译器支持出现在注释中的指令。除了少数为了兼容性而存在的例外情况外,这些注释指令都是以 //go:
开头的行注释,并且在 //
和 go:
之间没有空格。
go 工具指令
//go:build
go 工具支持构建约束。这些是 //go:build
指令,描述了文件应该包含在包中的条件。
约束的示例用法如下:
//go:build ignore
是一种约定,可以使文件不参与构建。这常用于生成源代码的程序。//go:build linux
只会在为 Linux 构建时编译文件。这通常可用于任何操作系统或架构。//go:build cgo
只会在支持 cgo 时编译文件。//go:build purego
是一种约定,只在使用纯 Go(即不包含 cgo 或汇编代码)时编译文件。
约束也可以是表达式
//go:build amd64 || arm64
将在 amd64 或 arm64 上编译文件。
约束可以设置编译文件时使用的语言版本。例如,约束 //go:build go1.23
只会在使用 Go 1.23 或更高版本时编译文件,并且在构建文件时会使用 Go 1.23 的语言语义。如果 go.mod 是较早的版本,这会很方便。例如,这允许定义提供 Go 1.23 函数迭代器的函数,但仅在使用 Go 1.23 或更高版本构建时才有效。
在 Go 1.16 及更早版本中,构建约束是使用以 // +build
开头的注释编写的,并且不允许使用通用表达式。gofmt 程序会将旧的 // +build
语法重写为新的 //go:build
语法。
//go:generate
go generate 命令查找 //go:generate
指令以找到要运行的命令。
此指令的一个示例是 //go:generate stringer -type=Enum
,用于运行 stringer 工具,为整数类型的值定义 String
方法。
//go:embed
embed 包使用 //go:embed
指令将源文件嵌入到生成的二进制文件中。单个文件可以嵌入为 string
或 []byte
。一组文件可以嵌入为 embed.FS
,它实现了 fs.FS
接口。
例如,可以使用以下指令将名为 templates 的子目录内容嵌入到程序中:
//go:embed templates
var templatesSource embed.FS
// tmpls holds the parsed embedded templates.
// This does not read files at run time,
// it parses the data embedded in the binary.
var tmpls = template.ParseFS(templatesSource)
编译器指令
Go 编译器支持多种指令。
//line
//line
指令允许设置后续代码使用的文件名、行号和列号。出于历史原因,此指令不以 //go:
开头。当 Go 文件是从其他源生成时,这很有用,它可以使错误消息或堆栈跟踪引用那个其他源文件,而不是生成的源文件。
在行内,可以使用 /*line
块注释,这对于设置列位置很有帮助。
//line foo.src:10
var x = /*line foo.src:20:5*/ 3
//go:noescape
//go:noescape
指令后面必须跟一个没有函数体的函数声明,表明该函数未在 Go 中实现。该指令告诉编译器,传递给函数的指针不会逃逸到堆上,也不会由函数返回。
其他编译器指令
还有许多其他编译器指令用于特殊目的。详细信息请参阅编译器文档。
//go:linkname
//go:noinline
//go:norace
//go:nosplit
//go:uintptrescapes
//go:wasmimport
未文档化的编译器指令
编译器还支持一些未文档化的指令。通常这些不应该在用户代码中使用。其中一些仅在编译 runtime 包时可用。
//go:nocheckptr
//go:nointerface
//go:nowritebarrier
//go:nowritebarrierrec
//go:registerparams
//go:systemstack
//go:uintptrkeepalive
//go:yeswritebarrierrec
cgo 注释
cgo 工具使用紧跟在 import "C"
语句之前的一系列注释。这一系列注释称为 cgo 前导区 (preamble),它们定义了 Go 代码可以使用特殊的 C
包引用的名称。
package main
// #include <stdio.h>
import "C"
func main() {
C.puts(C.CString("hello world"))
}
在前导区内,cgo 识别以 #cgo
开头的指令。这些指令可用于设置要使用的 C 编译器和链接器标志,或描述某些 C 函数的行为。详细信息请参阅cgo 文档。
cgo export
在使用 cgo 的文件中,可以使用 //export
指令使 Go 函数对 C 代码可见。语法是在 Go 函数 GoName
之前的注释中写入 //export CName
。这将安排使得 C 调用函数 CName
实际上会调用 Go 函数 GoName
。详细信息请参阅cgo 文档。
cgo 编译器指令
cgo 工具生成 Go 代码,生成的代码使用一些特殊指令,这些指令主要只在 cgo 生成的代码中可用。除了 cgo 源代码中,这些指令大多没有文档记录。
//go:cgo_dynamic_linker
//go:cgo_export_dynamic
//go:cgo_export_static
//go:cgo_import_dynamic
//go:cgo_import_static
//go:cgo_ldflag
//go:cgo_unsafe_args
此内容是 Go Wiki 的一部分。