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

未文档化的编译器指令

编译器还支持一些未文档化的指令。通常,这些不应在用户代码中使用。其中一些仅在编译运行时包时可用。

  • //go:nocheckptr
  • //go:nointerface
  • //go:nowritebarrier
  • //go:nowritebarrierrec
  • //go:registerparams
  • //go:systemstack
  • //go:uintptrkeepalive
  • //go:yeswritebarrierrec

cgo 注释

cgo 工具 使用在 import "C" 语句之前立即出现的一个或多个注释序列。这个注释序列,称为 cgo 序言,定义了 Go 代码可以使用特殊 C 包引用的名称。

package main

// #include <stdio.h>
import "C"

func main() {
    C.puts(C.CString("hello world"))
}

在序言中,cgo 识别以 #cgo 开头的指令。这些指令可用于设置要使用的 C 编译器和链接器标志,或描述某些 C 函数的行为。有关完整详细信息,请参阅 cgo 文档

cgo 导出

在使用 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 的一部分。