Every time you complete a Go module, you need to publish it if you want more people to use your code. This article explains how to publish a new module.

The original address: blog.golang.org/publishing-…

Introduction to the

This is the third article in a five-part series:

  • Using the Go Modules

  • Migrate to Go Modules

  • Release the Go Modules

  • Go Modules: V2 and later versions

  • Keep Modules compatible

This article discusses how to write and publish modules so that other modules can use them.

Please note: this article only covers the development of version V1. If you’re interested in the V2 version, see Go Modules: v2 and later.

This article uses Git version management as an example. Mercurial, Bazaar, and other version management tools are also supported.

Create a project

In this article, you need to use an existing project as an example. Here, continue with the code from the first article to demonstrate:

$cat go.mod module example.com/hello go 1.12 require rsc. IO /quote/v3 v3.1.0 $cat go.sum golang.org/x/text 14 c0d48ead0c v0.0.0-20170915032832 - h1: qgOY6WgZOaTkIIMiVjBQcw93ERBE4m30iBm00nkL0i8 = golang.org/x/text V0.0.0 c0d48ead0c/go - 20170915032832-14 mod h1: NqM8EUOU14njkJ3fqMW + pc6Ldnwhi/IjpwHt7yyuwOQ = RSC. IO/quote/v3 v3.1.0 H1:9 jkuttiugs6kzr9mk1yugkv6nl + DijDNIc0ghT58FaY = RSC. IO/quote/v3 v3.1.0 / go mod H1: yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD + tICJqUlj0 = RSC. IO/sampler v1.3.0 h1:7 uvkifmebqhfdjd + + RODJ2Wc4O7MPEh gZwtXXI/QiW4 = RSC. IO/sampler v1.3.0 / go mod h1: T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA = $cat hello. Go package hello import "rsc.io/quote/v3" func Hello() string { return quote.HelloV3() } func Proverb() string { return quote.Concurrency() } $ cat hello_test.go package hello import ( "testing" ) func TestHello(t *testing.T) { want := "Hello, world." if got := Hello(); got ! = want { t.Errorf("Hello() = %q, want %q", got, want) } } func TestProverb(t *testing.T) { want := "Concurrency is not parallelism." if got := Proverb(); got ! = want { t.Errorf("Proverb() = %q, want %q", got, want) } } $Copy the code

Next, create a new Git repository and add an initial commit. If you publish your own project, add a LICENSE file. Switch to the directory containing the go.mod file and create a repository:

$ git init
$ git add LICENSE go.mod go.sum hello.go hello_test.go
$ git commit -m "hello: initial commit"
$
Copy the code

Semantic versions and modules

Each module has a semantic version in the go.mod file, which is the smallest version of the dependencies used to build the module.

The format for a semantic version number is vmajor.minor.patch:

  • The major version is added only when backward incompatible changes are made to the module’s public API. Do this only when necessary.

  • Minor versions are added when backward compatible changes are made to the API, such as changing dependencies or adding new functions, methods, structural fields, or types.

  • Patch versions are added after minor changes are made that do not affect the module’s public API or dependencies, such as bug fixes.

You can specify pre-release versions by appending hyphens and dot-separated identifiers (for example, V1.0.1-alpha or V2.2.2-beta.2). The go command preferentially uses the normal version over the pre-release version, so if your module already has a normal version, users must specify the version number if they want to use the pre-release version (for example, go to example.com/[email protected]).

V0 major and pre-release versions do not guarantee backward compatibility. They allow you to optimize your API without making a stable release promise to your users. However, the V1 major and other releases need to be compatible within that major.

The version referenced in go.mod may be an explicit release marked in the repository (for example, v1.5.2) or a pseudo-version based on a specific commit (for example, v0.0.0-20170915032832-14c0d48eAD0c). Pseudo-version is a special type of pre-release version. Pseudo versions are useful when users need to rely on a project that has not published any semantic version markers, or when developing against a commit that has not yet been marked. But users should not assume that pseudo-version provides a stable or well-tested API. Marking modules with an explicit version number indicates to the user that a particular version has been adequately tested and is ready for use.

Once you start marking your repository with a version number, you should continue marking the new version as the module develops. When a user requests a new version of the module (using go get -u or Go get example.com/hello), the go command selects the largest semantic version available, even if that version has been around for several years and there are many changes behind the main branch. Continuing to mark new releases will enable your users to continue to improve.

Do not remove version tags from your repository. If you find bugs or security issues with a version, release a new version. If people rely on a version you’ve removed, their build will probably fail. Similarly, once you release a version, do not change or overwrite it. Module mirroring and checksum databases store the version and signature cryptographic hashes of modules to ensure that the build of a given version is constant over time.

V0: initial, unstable version

Let’s tag this module with the V0 semantic version. The V0 version does not make any stability guarantees, so almost all projects should start with V0 to improve the public API.

Marking a new version involves the following steps:

  1. Run Go Mod Tidy to remove dependencies that may no longer be used

  2. Run go test./.. “, and finally make sure that all functions are normal

  3. Mark a new version with the git tag command

  4. Push the tag to the remote repository

    gomodtidygo mod tidygomodtidy go test ./… Ok example.com/hello 0.015 s gitaddgo. Modgo. Sumhello. Gohellotest. Gogit add. Mod. Sum hello. Go hello_test.gogitaddgo.modgo.sumhello.gohellotest.go git commit -m “hello: Changes for v0.1.0” gittagv0.1.0git tagv0.1.0git push Origin v0.1.0 $

Other projects can now rely on v0.1.0 of example.com/hello. For your own modules, run go list -m example.com/[email protected] to verify the latest available version (the sample module does not exist, so there is no available version). If you don’t see the latest version immediately and are using the Go module agent (the default since Go 1.13), try again in a few minutes to give the agent a little time to load the new version.

If you add content to a public API, make a disruptive change to a v0 version of a module, or upgrade a minor version of a dependency, add a minor version for the next release. For example, the next version after V0.1.0 will be V0.2.0.

If bugs in the existing version are fixed, the patch version is added. For example, the next release after V0.1.0 will be V0.1.1.

V1: first stable release

Once you are sure that your module API is stable, you can release V1.0.0. The V1 major tells the user that no incompatible changes will be made to the module’s API. They can upgrade to the new V1 minor and patch versions and their code should not go wrong. Function and method signatures are not changed, exported types are not deleted, and so on. If the API changes, they will be backward-compatible (for example, adding new fields to the structure) and will be included in the next release. If bugs are fixed (for example, security fixes), they are included in the patch release (or as part of the next release).

Sometimes, maintaining backward compatibility can cause an API to be inelegant. But no matter, an imperfect API is better than breaking the user’s existing code.

The Strings package for the standard library is a prime example of maintaining backward compatibility at the expense of API consistency.

  • The Split function splits the string into substrings separated by separators and returns a substring slice separated by those separators

  • The SplitN function can be used to control the number of substrings to return

However, the Replace function determines the number of strings to Replace from the beginning (unlike the Split function).

Since there are Split and SplitN functions, you would expect to have Replace and ReplaceN functions as well. We cannot modify the Replace function without making destructive changes. In Go 1.12, we added a new function, ReplaceAll. Because Split and Replace behave differently, the resulting API is a bit strange, but this inconsistency is better than a disruptive change.

Let’s say you are now happy with example.com/hello’s API and want to release V1 as the first stable release.

The procedure for tagging V1 is the same as the procedure for tagging the V0 version: run Go Mod Tidy and Go test./.. , mark the version and push the tag to the remote repository:

$ go mod tidy $ go test ./... Ok example.com/hello 0.015s $git add go.mod go.sum hello.go hello_test.go $git commit -m "hello: Changes for v1.0.0" $git tag v1.0.0 $git push origin v1.0.0 $Copy the code

As of now, the V1 version of the API at example.com/hello has been documented. This communicates to everyone that our API is stable and that they should be comfortable with it.

conclusion

This article describes the process of tagging modules with semantic versions and when to release version V1. The following article will cover how to maintain and publish modules for V2 and later versions.

Please send us bug reports and experience reports to help us improve Go’s dependency management features.

Thank you for all your feedback and suggestions to help improve the module.

In addition, Tencent cloud blockchain direction in a large number of recruitment, including front-end, back-end, architect, product and many other positions, if interested, please send your resume to [email protected].

Translation/Rayjun