模块发布和版本控制工作流

当您开发供其他开发人员使用的模块时,可以遵循一个工作流,以帮助确保使用该模块的开发人员获得可靠、一致的体验。本主题描述了该工作流中的高级步骤。

有关模块开发的概述,请参阅开发和发布模块

另请参阅

  • 如果您只是想在代码中使用外部包,请务必查看管理依赖项
  • 对于每个新版本,您都通过其版本号来表示模块的更改。有关更多信息,请参阅模块版本号

常见工作流步骤

以下序列说明了新模块发布和版本控制工作流的步骤。有关每个步骤的更多信息,请参阅本主题中的部分。

  1. 开始一个模块并组织其源代码,以便开发人员更容易使用和您更容易维护。

    如果您是模块开发新手,请查看教程:创建一个Go模块

    在Go的去中心化模块发布系统中,您组织代码的方式很重要。有关更多信息,请参阅管理模块源代码

  2. 设置编写本地客户端代码,该代码调用未发布的模块中的函数。

    在您发布模块之前,它无法用于使用go get等命令的典型依赖管理工作流。在此阶段测试模块代码的好方法是在其位于调用代码的本地目录中时进行尝试。

    有关本地开发的更多信息,请参阅针对未发布的模块进行编码

  3. 当模块代码准备好供其他开发人员试用时,开始发布v0预发布版本,例如alpha和beta版本。有关更多信息,请参阅发布预发布版本

  4. 发布一个v0版本,该版本不保证稳定,但用户可以试用。有关更多信息,请参阅发布第一个(不稳定)版本

  5. 您的v0版本发布后,您可以(并且应该!)继续发布新版本

    这些新版本可能包括错误修复(补丁版本)、模块公共API的添加(次要版本),甚至是不兼容的更改。由于v0版本不保证稳定性或向后兼容性,您可以在其版本中进行不兼容的更改。

    有关更多信息,请参阅发布错误修复发布非不兼容API更改

  6. 当您准备发布稳定版本时,您将预发布版本发布为alpha和beta版本。有关更多信息,请参阅发布预发布版本

  7. 发布v1作为第一个稳定版本

    这是第一个对模块稳定性做出承诺的发布。有关更多信息,请参阅发布第一个稳定版本

  8. 在v1版本中,继续修复错误,并在必要时对模块的公共API进行添加。

    有关更多信息,请参阅发布错误修复发布非不兼容API更改

  9. 当无法避免时,在新主要版本中发布不兼容的更改。

    主要版本更新(例如从v1.x.x到v2.x.x)对于模块用户来说可能是一个非常具有破坏性的升级。它应该作为最后手段。有关更多信息,请参阅发布不兼容API更改

针对未发布的模块进行编码

当您开始开发模块或模块的新版本时,您尚未发布它。在您发布模块之前,您将无法使用Go命令将该模块添加为依赖项。相反,起初,当在调用未发布模块中函数的不同模块中编写客户端代码时,您需要引用本地文件系统上的模块副本。

您可以使用客户端模块的go.mod文件中的replace指令从客户端模块的go.mod文件本地引用模块。有关更多信息,请参阅在本地目录中要求模块代码

发布预发布版本

您可以发布预发布版本,以便其他人可以试用模块并向您提供反馈。预发布版本不保证稳定性。

预发布版本号后附加预发布标识符。有关版本号的更多信息,请参阅模块版本号

以下是两个示例

v0.2.1-beta.1
v1.2.3-alpha

在提供预发布版本时,请记住,使用预发布版本的开发人员需要使用go get命令通过版本明确指定它。这是因为,默认情况下,go命令在查找您请求的模块时更喜欢发布版本而不是预发布版本。因此,开发人员必须通过明确指定预发布版本来获取它,如以下示例所示

go get example.com/theirmodule@v1.2.3-alpha

您通过在存储库中标记模块代码来发布预发布版本,并在标签中指定预发布标识符。有关更多信息,请参阅发布模块

发布第一个(不稳定)版本

与发布预发布版本一样,您可以发布不保证稳定性或向后兼容性的发布版本,但让您的用户有机会试用模块并向您提供反馈。

不稳定版本是版本号在v0.x.x范围内的版本。v0版本不作任何稳定性或向后兼容性保证。但它为您提供了一种在v1及更高版本做出稳定性承诺之前获取反馈和完善API的方法。有关更多信息,请参阅模块版本号

与其他已发布版本一样,您可以在进行更改以发布稳定的v1版本时,递增v0版本号的次要和补丁部分。例如,在发布v.0.0.0之后,您可能会发布带有第一组错误修复的v0.0.1。

这是一个版本号示例

v0.1.3

您通过在存储库中标记模块代码来发布不稳定版本,并在标签中指定v0版本号。有关更多信息,请参阅发布模块

发布第一个稳定版本

您的第一个稳定版本将具有v1.x.x版本号。第一个稳定版本是在您通过预发布和v0版本获得反馈、修复错误并为用户稳定模块之后发布的。

通过v1版本,您向使用您模块的开发人员做出以下承诺

  • 他们可以升级到主要版本的后续次要和补丁版本,而不会破坏自己的代码。
  • 您将不再对模块的公共API(包括其函数和方法签名)进行任何破坏向后兼容性的更改。
  • 您将不会删除任何导出的类型,因为这会破坏向后兼容性。
  • 您API的未来更改(例如向结构体添加新字段)将向后兼容,并将包含在新的次要版本中。
  • 错误修复(例如安全修复)将包含在补丁版本中或作为次要版本的一部分。

注意:虽然您的第一个主要版本可能是v0版本,但v0版本不表示稳定性或向后兼容性保证。因此,当您从v0递增到v1时,您不必担心破坏向后兼容性,因为v0版本不被认为是稳定的。

有关版本号的更多信息,请参阅模块版本号

这是一个稳定版本号的示例

v1.0.0

您通过在存储库中标记模块代码来发布第一个稳定版本,并在标签中指定v1版本号。有关更多信息,请参阅发布模块

发布错误修复

您可以发布一个只包含错误修复的发布版本。这被称为补丁版本。

补丁版本只包含细微的更改。特别是,它不包含对模块公共API的任何更改。使用代码的开发人员可以安全地升级到此版本,而无需更改其代码。

注意:您的补丁版本应尽量不要将其自身的任何传递依赖项升级超过一个补丁版本。否则,升级到您模块补丁版本的人可能会意外地引入他们使用的传递依赖项的更具侵入性的更改。

补丁版本递增模块版本号的补丁部分。有关更多信息,请参阅模块版本号

在以下示例中,v1.0.1是一个补丁版本。

旧版本:v1.0.0

新版本:v1.0.1

您通过在存储库中标记模块代码来发布补丁版本,并在标签中递增补丁版本号。有关更多信息,请参阅发布模块

发布非破坏性API更改

您可以对模块的公共API进行非破坏性更改,并在次要版本发布中发布这些更改。

此版本更改了API,但不会以破坏调用代码的方式进行。这可能包括对模块自身依赖项的更改或新函数、方法、结构体字段或类型的添加。即使包含这些更改,此类发布仍保证现有调用模块函数的代码的向后兼容性和稳定性。

次要版本递增模块版本号的次要部分。有关更多信息,请参阅模块版本号

在以下示例中,v1.1.0是一个次要版本。

旧版本:v1.0.1

新版本:v1.1.0

您通过在存储库中标记模块代码来发布次要版本,并在标签中递增次要版本号。有关更多信息,请参阅发布模块

发布破坏性API更改

您可以通过发布主要版本发布来发布破坏向后兼容性的版本。

主要版本发布不保证向后兼容性,通常是因为它包含对模块公共API的更改,这些更改会破坏使用模块先前版本的代码。

鉴于主要版本升级可能对依赖模块的代码产生破坏性影响,如果可能,您应该避免主要版本更新。有关主要版本更新的更多信息,请参阅开发主要版本更新。有关避免进行破坏性更改的策略,请参阅博客文章保持模块兼容

发布其他类型的版本基本上只需用版本号标记模块代码,而发布主要版本更新则需要更多步骤。

  1. 在新主要版本开发开始之前,在您的存储库中为新版本的源代码创建一个位置。

    一种方法是在您的存储库中创建一个专门用于新主要版本及其后续次要和补丁版本的新分支。有关更多信息,请参阅管理模块源代码

  2. 在模块的go.mod文件中,修改模块路径以附加新的主要版本号,如以下示例所示

    example.com/mymodule/v2
    

    鉴于模块路径是模块的标识符,此更改有效地创建了一个新模块。它还更改了包路径,确保开发人员不会无意中导入一个破坏其代码的版本。相反,那些想要升级的人将明确地用新路径替换旧路径的出现。

  3. 在您的代码中,更改您正在更新的模块中导入包的任何包路径,包括您正在更新的模块中的包。您需要这样做是因为您更改了模块路径。

  4. 与任何新发布一样,您应该发布预发布版本以获取反馈和错误报告,然后再发布正式版本。

  5. 通过在存储库中标记模块代码来发布新的主要版本,并在标签中递增主要版本号——例如从v1.5.2到v2.0.0。

    有关更多信息,请参阅发布模块