贡献指南

Go 项目欢迎所有贡献者。

本文档旨在指导您完成 Go 项目的贡献过程,这与其他开源项目的贡献方式略有不同。我们假设您对 Git 和 Go 有基本的了解。

除了此处的信息外,Go 社区还维护了一个代码审查维基页面。在学习审查过程时,请随时为该维基页面做出贡献。

请注意,gccgo前端位于其他位置;请参阅贡献给 gccgo

成为贡献者

概览

第一步是注册成为 Go 贡献者并配置您的环境。以下是需要遵循的步骤清单:

如果您愿意,有一个自动化工具可以引导您完成这些步骤。只需运行

$ go install golang.org/x/tools/cmd/go-contrib-init@latest
$ cd /code/to/edit
$ go-contrib-init

本章的其余部分将详细阐述这些说明。如果您已完成上述步骤(无论是手动还是通过工具),请跳转到贡献代码之前

第 0 步:选择一个 Google 帐号

对 Go 的贡献是通过具有特定电子邮件地址的 Google 帐号完成的。请务必在整个过程中以及您随后的所有贡献中使用同一个帐号。您可能需要决定是使用个人地址还是公司地址。选择将取决于谁将拥有您将编写和提交的代码的版权。您可能希望在决定使用哪个帐号之前与您的雇主讨论此主题。

Google 帐号可以是 Gmail 电子邮件帐号、G Suite 组织帐号,或与外部电子邮件地址关联的帐号。例如,如果您需要使用现有但并非通过 G Suite 管理的公司电子邮件,您可以创建与您现有电子邮件地址关联的帐号

您还需要确保您的 Git 工具已配置为使用您选择的电子邮件地址创建提交。您可以全局配置 Git(作为所有项目的默认设置),或局部配置 Git(针对单个特定项目)。您可以使用此命令检查当前配置:

$ git config --global user.email  # check current global config
$ git config user.email           # check current local config

要更改已配置的地址:

$ git config --global user.email name@example.com   # change global config
$ git config user.email name@example.com            # change local config

第 1 步:贡献者许可协议

在向 Go 项目发送您的第一个更改之前,您必须已完成以下两个 CLA 之一。您应该签署哪个 CLA 取决于谁拥有您作品的版权。

您可以在Google 开发者贡献者许可协议网站上查看您当前已签署的协议并签署新的协议。如果您的贡献的版权持有人已就另一个 Google 开源项目完成了协议,则无需再次完成。

如果您提交的代码的版权持有人发生变更——例如,如果您开始代表新公司贡献代码——请发送邮件至golang-dev 邮件列表。这将让我们了解情况,以便我们确保完成适当的协议。

第 2 步:配置 git 身份验证

主要的 Go 仓库位于go.googlesource.com,这是一个由 Google 托管的 Git 服务器。Web 服务器上的身份验证通过您的 Google 帐号进行,但您还需要在计算机上配置 git 才能访问它。请按照以下步骤操作:

  1. 访问go.googlesource.com,然后点击页面右上角菜单栏中的“生成密码”。您将被重定向到 accounts.google.com 进行登录。
  2. 登录后,您将进入一个标题为“配置 Git”的页面。此页面包含一个个性化脚本,该脚本在本地运行时将配置 Git 以保存您的唯一身份验证密钥。此密钥与服务器上生成和存储的密钥配对,类似于 SSH 密钥的工作方式。
  3. 复制此脚本并在本地终端中运行,将您的秘密身份验证令牌存储在 .gitcookies 文件中。如果您使用的是 Windows 计算机并运行 cmd,则应按照黄色框中的说明运行该命令;否则运行常规脚本。

第 3 步:创建 Gerrit 帐号

Gerrit 是 Go 维护者用于讨论和审查代码提交的开源工具。

要注册您的帐号,请访问go-review.googlesource.com/login/,并使用您上面使用的同一个 Google 帐号登录一次。

第 4 步:安装 git-codereview 命令

无论谁进行更改,Go 的更改都必须经过审查才能被接受。一个名为 git-codereview 的自定义 git 命令简化了向 Gerrit 发送更改的过程。

通过运行以下命令安装 git-codereview 命令:

$ go install golang.org/x/review/git-codereview@latest

确保 git-codereview 已安装在您的 shell 路径中,以便 git 命令能够找到它。检查

$ git codereview help

会打印帮助文本,而不是错误。如果打印错误,请确保 $GOPATH/bin 在您的 $PATH 中。

在 Windows 上,使用 git-bash 时,您必须确保 git-codereview.exe 在您的 git exec-path 中。运行 git --exec-path 以发现正确的路径,然后创建符号链接或直接将可执行文件从 $GOPATH/bin 复制到此目录。

贡献代码之前

该项目欢迎代码补丁,但为确保协调良好,您应在开始工作之前讨论任何重大更改。建议您在问题跟踪器中表明您的贡献意图,可以通过提出新问题或认领现有问题

在哪里贡献

Go 项目由主要的go仓库组成,该仓库包含 Go 语言的源代码,以及许多 golang.org/x/... 仓库。这些仓库包含支持 Go 的各种工具和基础设施。例如,golang.org/x/pkgsite 用于pkg.go.devgolang.org/x/playground 用于 Go playground,golang.org/x/tools 包含各种 Go 工具,包括 Go 语言服务器gopls。您可以在go.googlesource.com上查看所有 golang.org/x/... 仓库的列表。

检查问题跟踪器

无论您是否已经知道要做出什么贡献,或者您正在寻找一个想法,问题跟踪器始终是首选。问题经过分类以对其进行归类和管理工作流程。

大多数 golang.org/x/... 仓库也使用主要的 Go 问题跟踪器。但是,其中一些仓库单独管理其问题,因此请务必为要贡献的仓库检查正确的问题跟踪器。

大多数问题将用以下工作流标签之一标记:

您可以使用 GitHub 的搜索功能来查找可以帮助解决的问题。示例:

为任何新问题开一个 issue

除了非常微不足道的更改外,所有贡献都应与现有问题相关联。请随时开一个 issue 并讨论您的计划。这个过程让每个人都有机会验证设计,有助于防止重复工作,并确保想法符合语言和工具的目标。它还在编写代码之前检查设计是否合理;代码审查工具不是进行高层讨论的地方。

在规划工作时,请注意 Go 项目对主要的 Go 仓库遵循六个月的开发周期。每个周期的后半部分是为期三个月的特性冻结期,在此期间只接受错误修复和文档更新。新的贡献可以在特性冻结期间发送,但直到冻结结束才能合并。冻结适用于整个主仓库以及构建发布中包含的二进制文件所需的 golang.org/x/... 仓库中的代码。请参阅标准库go 命令中供应商的包列表。

对语言、库或工具的重大更改(包括主仓库和所有 golang.org/x 仓库中的 API 更改,以及 go 命令的命令行更改)在接受之前必须经过更改提案流程

敏感的安全相关问题(仅限!)应报告给security@golang.org

通过 GitHub 发送更改

熟悉GitHub 流程的首次贡献者,建议使用相同的流程进行 Go 贡献。尽管 Go 维护者使用 Gerrit 进行代码审查,但已创建一个名为 Gopherbot 的机器人,用于将 GitHub 拉取请求同步到 Gerrit。

像往常一样打开一个 GitHub 拉取请求。Gopherbot 将创建一个相应的 Gerrit 更改列表(一个“CL”)并在您的 GitHub 拉取请求上发布一个链接;对拉取请求的更新也会反映在 Gerrit CL 中。当有人对 CL 发表评论时,他们的评论也会发布在您的拉取请求中,因此您将收到通知。

需要注意的一些事项:

通过 Gerrit 发送更改

目前,Gerrit 和 GitHub 无法完全同步,所以我们建议学习 Gerrit。它有所不同但功能强大,熟悉它将帮助您理解流程。

以下部分简要介绍了通过 Gerrit 提交更改的步骤。有关与 Gerrit 交互的更多详细信息,请参阅Gerrit 的文档。特别是,我们建议阅读审查 UI 概述Gerrit 基本操作指南——适用于 GitHub 用户页面。

概览

以下是整体流程概述:

本节的其余部分将更详细地描述这些步骤。

第 1 步:克隆源代码

除了最新的 Go 安装外,您还需要从正确的仓库检出源代码的本地副本。您可以将 Go 源代码仓库检出到本地文件系统的任何位置,只要它在您的 GOPATH 之外(默认为您主目录中的 go 目录)。从 go.googlesource.com 克隆(而不是 GitHub)

主要的 Go 仓库

$ git clone https://go.googlesource.com/go
$ cd go

golang.org/x/... 仓库

(在此示例中为golang.org/x/tools
$ git clone https://go.googlesource.com/tools
$ cd tools

第 2 步:在新分支中准备更改

每个 Go 更改都必须在从 master 分支创建的单独分支中进行。您可以使用正常的 git 命令来创建分支并将更改添加到暂存区

$ git checkout -b mybranch
$ [edit files...]
$ git add [files...]

要提交更改,请使用 git codereview change,而不是 git commit

$ git codereview change
(open $EDITOR)

您可以像往常一样在您喜欢的编辑器中编辑提交描述。 git codereview change 命令会自动在底部附近添加一个唯一的 Change-Id 行。Gerrit 使用该行来匹配同一更改的后续上传。请勿编辑或删除它。Change-Id 如下所示:

Change-Id: I2fbdbffb3aab626c4b6f56348861b7909e3e8990

该工具还会检查您是否已对源代码运行 go fmt,并且提交消息遵循建议的格式

如果您需要再次编辑文件,可以暂存新更改并重新运行 git codereview change:每次后续运行都会修改现有提交,同时保留 Change-Id。

确保每个分支中始终只保留一个提交。如果您不小心添加了更多提交,可以使用 git rebase 将它们合并为一个。

第 3 步:测试您的更改

您已经编写并测试了您的代码,但在发送代码进行审查之前,请运行整个树的所有测试以确保更改不会破坏其他包或程序。

在主 Go 仓库中

对于标准库包,包内的所有测试都必须通过

$ go test

可以使用 all.bash 运行整个树的短测试套件(在 Windows 下构建使用 all.bat

$ cd go/src
$ ./all.bash

运行一段时间并打印大量测试输出后,命令应以打印以下内容结束:

ALL TESTS PASSED

您可以使用 make.bash 而不是 all.bash 来只构建编译器和标准库而不运行测试套件。一旦 go 工具构建完成,它将作为 bin/go 安装在您克隆 Go 仓库的目录下,您可以直接从那里运行它。另请参阅有关如何快速测试您的更改的部分。

在 golang.org/x/... 仓库中

运行整个仓库的测试(在此示例中为golang.org/x/tools

$ cd tools
$ go test ./...

如果您担心构建状态,可以查看构建仪表板。测试失败也可能被代码审查中的 TryBots 捕获。

一些仓库,例如golang.org/x/vscode-go将具有不同的测试基础设施,因此请务必检查您正在处理的仓库的文档。仓库根目录下的 README 文件通常会包含此信息。

第 4 步:发送更改进行审查

一旦更改准备就绪并在整个树上测试通过,就将其发送进行审查。这通过 mail 子命令完成,尽管其名称如此,但它不直接发送任何邮件;它只是将更改发送到 Gerrit。

$ git codereview mail

Gerrit 会为您的更改分配一个编号和 URL, git codereview mail 将打印出来,类似这样:

remote: New Changes:
remote:   https://go-review.googlesource.com/99999 math: improved Sin, Cos and Tan precision for very large arguments

如果出现错误,请检查邮件错误疑难解答部分。

如果您的更改与一个开放的 GitHub issue 相关,并且您遵循了建议的提交消息格式,那么一个机器人将在几分钟内更新该 issue,在评论中将您的 Gerrit 更改链接到该 issue。

第 5 步:审查后修改更改

Go 维护者将在 Gerrit 上审查您的代码,您将通过电子邮件收到通知。您可以在 Gerrit 上查看审查并发表评论。如果您愿意,也可以使用电子邮件回复

如果您需要在审查后修改您的更改,请在您之前创建的同一分支中编辑文件,将它们添加到 Git 暂存区,然后使用 git codereview change 修改提交

$ git codereview change     # amend current commit
(open $EDITOR)
$ git codereview mail       # send new changes to Gerrit

如果您不需要更改提交描述,只需保存并退出编辑器。请记住不要更改特殊的 Change-Id 行。

再次强调,确保每个分支中始终只保留一个提交。如果您不小心添加了更多提交,可以使用 git rebase 将它们合并为一个。

良好的提交消息

Go 中的提交消息遵循一套特定的约定,我们将在本节中讨论。

以下是一个很好的例子:

math: improve Sin, Cos and Tan precision for very large arguments

The existing implementation has poor numerical properties for
large arguments, so use the McGillicutty algorithm to improve
accuracy above 1e10.

The algorithm is described at https://wikipedia.org/wiki/McGillicutty_Algorithm

Fixes #159

第一行

更改描述的第一行通常是更改的简短单行摘要,并以主要受影响的包为前缀。

经验法则是,它应该这样编写,以完成“此更改将 Go 修改为 _____。”这句话。这意味着它不以大写字母开头,不是一个完整的句子,并且确实总结了更改的结果。

第一行后跟一个空行。

主要内容

其余的描述应详细阐述并提供更改的上下文,并解释其作用。像您在 Go 中的注释一样,用完整的句子和正确的标点符号书写。不要使用 HTML、Markdown 或任何其他标记语言。

添加任何相关信息,例如如果更改影响性能,则添加基准测试数据。通常使用 benchstat 工具来格式化基准测试数据以用于更改描述。

引用问题

特殊符号“Fixes #12345”将更改与Go 问题跟踪器中的问题 12345 相关联。当此更改最终应用时,问题跟踪器将自动将该问题标记为已修复。

如果更改是解决问题的部分步骤,请改为写入“Updates #12345”。这将在问题中留下一个评论,链接回 Gerrit 中的更改,但当更改应用时,它不会关闭问题。

如果您要向 golang.org/x/... 仓库发送更改,则必须使用 GitHub 支持的完全限定语法,以确保更改链接到主仓库中的问题,而不是 x/ 仓库。大多数问题都在主仓库的问题跟踪器中跟踪。正确的形式是“Fixes golang/go#159”。

审查过程

本节详细解释了审查过程以及在发送更改后如何处理审查。

常见的初学者错误

当更改发送到 Gerrit 时,通常会在几天内进行分类。维护人员将查看并提供一些初步审查,对于首次贡献者,通常侧重于基本的外观和常见错误。这些包括:

试运行机器人(Trybots)

在初步阅读您的更改后,维护人员将触发试运行机器人,这是一个服务器集群,将在几种不同的架构上运行完整的测试套件。大多数试运行机器人在几分钟内完成,届时将在 Gerrit 中发布一个链接,您可以在其中查看结果。

如果试运行机器人运行失败,请按照链接检查测试失败的平台的完整日志。尝试了解发生了什么故障,更新您的补丁以修复它,然后再次上传。维护者将触发新的试运行机器人运行以查看问题是否已修复。

有时,某些平台上的树可能会中断几个小时;如果试运行机器人报告的故障似乎与您的补丁无关,请转到构建仪表板并检查同一故障是否出现在同一平台上其他最近的提交中。在这种情况下,请随意在 Gerrit 中写评论,提及故障与您的更改无关,以帮助维护者了解情况。您还可以搜索 GitHub issue 中失败的错误消息,或浏览最近更新的 watchflakes issue。如果您的更改基于较旧的提交,或者看起来其他人可能已经解决了问题,请尝试通过 git rebase 重新基于最新的 master 提交。

审查

Go 社区非常重视彻底的审查。将每个审查评论视为一张工单:您应该通过对其采取行动来“关闭”它,无论是实施建议还是说服审阅者。

更新更改后,请仔细查看审查评论并确保回复每一个。您可以单击“完成”按钮来回复,表明您已实施审阅者的建议;否则,单击“回复”并解释您为什么没有或您做了什么。

更改经过几轮审查是完全正常的,一个或多个审阅者每次都会提出新的评论,然后等待更新的更改才能再次审查。这个循环甚至对经验丰富的贡献者也会发生,所以不要因此而气馁。

投票惯例

当他们接近决定时,审阅者将对您的更改应用 Code-Review“投票”。有两种可能的投票:

要提交,更改必须获得维护者的 Code-Review +2。

维护者也可以对更改应用 Hold +1 投票,以标记不应立即提交的更改(例如,因为更改中新 API 的提案审查尚未完成)。

要提交,更改不得有维护者的任何 Hold +1 投票。

最后,要提交更改,必须有两名 Google 员工参与,可以是更改的上传者,也可以是投票至少为 Code-Review +1 的审阅者。此要求出于合规性和供应链安全原因。

提交已批准的更改

当更改准备就绪时,维护者将提交更改,将其作为提交添加到 Gerrit 仓库中。

这两个步骤(批准和提交)是分开的,因为在某些情况下,维护者可能希望批准它但不会立即提交它(例如,树可能暂时被冻结)。

提交更改会将其检入仓库。更改描述将包含指向代码审查的链接,该链接将更新为指向仓库中更改的链接。由于用于集成更改的方法是 Git 的“Cherry Pick”,因此提交操作将更改仓库中的提交哈希。

如果您的更改已批准几天但尚未提交,请随时在 Gerrit 中发表评论,请求提交。

更多信息

除了这里的信息,Go 社区还维护了一个代码审查维基页面。在您进一步了解审查过程时,请随意为此页面做出贡献。

其他主题

本节收集了许多超出 issue/编辑/代码审查/提交过程本身的评论。

Gopls

在主 Go 仓库上工作并使用编辑器中的 gopls 时,由 gopls 调用的 go 命令必须与您正在使用的源代码版本相对应。 go 命令可以使用 make.bash 构建,并且 bin 目录应添加到您的 PATH 中。有关其他详细信息,请参阅Gopls:高级主题

Gopls 的完整文档可在 https://golang.ac.cn/gopls 找到。

Go 仓库中的文件不列出作者姓名,既为了避免混乱,也为了避免不得不保持列表最新。相反,您的姓名将出现在更改日志中。

您贡献的新文件应使用标准版权头

// Copyright 2025 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

仓库中的文件在添加年份受版权保护。请勿更新您更改的文件的版权年份。

邮件错误疑难解答

git codereview mail 命令失败最常见的原因是提交中的电子邮件地址与您在注册过程中使用的电子邮件地址不匹配。
如果你看到类似...的情况

remote: Processing changes: refs: 1, done
remote:
remote: ERROR:  In commit ab13517fa29487dcf8b0d48916c51639426c5ee9
remote: ERROR:  author email address XXXXXXXXXXXXXXXXXXX
remote: ERROR:  does not match your user account.

你需要为这个仓库配置 Git,以使用你注册的电子邮件地址。要更改电子邮件地址以确保这种情况不再发生,请运行:

$ git config user.email email@address.com

然后使用此命令更改提交以使用此替代电子邮件地址:

$ git commit --amend --author="Author Name <email@address.com>"

然后重试运行:

$ git codereview mail

快速测试您的更改

对于代码树的每一次更改都运行 all.bash 是很麻烦的。尽管强烈建议在发送更改之前运行它,但在正常的开发周期中,您可能只希望编译和测试您正在开发的包。

指定审阅者 / 抄送他人

除非另有明确说明(例如在发送更改之前的讨论中),否则最好不要指定审阅者。所有更改都会自动抄送至 golang-codereviews@googlegroups.com 邮件列表。如果这是您的首次更改,可能会有审核延迟才能出现在邮件列表中,以防止垃圾邮件。

您可以使用 -r-cc 选项指定审阅者或抄送相关方。两者都接受逗号分隔的电子邮件地址列表

$ git codereview mail -r joe@golang.org -cc mabel@example.com,math-nuts@swtch.com

同步您的客户端

在您工作期间,其他人可能已向仓库提交更改。要更新您的本地分支,请运行:

$ git codereview sync

(其内部运行 git pull -r。)

审查他人的代码

作为审查过程的一部分,审阅者可以直接提出更改(在 GitHub 工作流中,这将是其他人将提交附加到拉取请求)。Gerrit 提供对命令的访问,这些命令将帮助您导入其他开发人员提出的更改,以便您可以在本地审查/测试它们。从要导入的 CL 的 Gerrit 页面,打开“⋮”菜单,单击“下载补丁”链接。根据您首选的 git 工作流,选择适当的命令。选项将如下所示:

$ git fetch https://go.googlesource.com/review refs/changes/21/13245/1 && git checkout FETCH_HEAD

要恢复,请切换回您正在工作的分支。

设置 git 别名

git-codereview 命令可以直接从 shell 运行,例如,键入

$ git codereview sync

但更方便的是为 git-codereview 的子命令设置别名,这样上面就变成了:

$ git sync

git-codereview 子命令已被选择与 Git 自己的子命令区分开来,因此定义这些别名是安全的。要安装它们,请将此文本复制到您的 Git 配置文件中(通常是您主目录中的 .gitconfig):

[alias]
	change = codereview change
	gofmt = codereview gofmt
	mail = codereview mail
	pending = codereview pending
	submit = codereview submit
	sync = codereview sync

发送多个相关联的更改

高级用户可能希望在一个分支中堆叠相关的提交。Gerrit 允许更改相互依赖,从而形成这样的依赖链。每个更改都需要单独批准和提交,但依赖关系将对审阅者可见。

要发送一组相关的更改,请将每个更改作为同一分支下的不同提交,然后运行:

$ git codereview mail HEAD

确保明确指定 HEAD,这在发送单个更改时通常不需要。更多详细信息可在git-codereview 文档中找到。

次要版本

如果您想对发布分支进行更改以进行回溯,请参阅次要版本