diff options
Diffstat (limited to 'content/migrating-to-go-modules.article')
-rw-r--r-- | content/migrating-to-go-modules.article | 101 |
1 files changed, 51 insertions, 50 deletions
diff --git a/content/migrating-to-go-modules.article b/content/migrating-to-go-modules.article index e3c8759..10bf730 100644 --- a/content/migrating-to-go-modules.article +++ b/content/migrating-to-go-modules.article @@ -1,24 +1,25 @@ -Migrating to Go Modules +# Migrating to Go Modules 21 Aug 2019 Tags: tools, versioning, modules +Summary: This post is part 2 in a series. Jean de Klerk -* Introduction +## Introduction This post is part 2 in a series. -- Part 1 — [[/using-go-modules][Using Go Modules]] -- *Part*2*—*Migrating*To*Go*Modules* (this post) -- Part 3 — [[/publishing-go-modules][Publishing Go Modules]] -- Part 4 — [[/v2-go-modules][Go Modules: v2 and Beyond]] + - Part 1 — [Using Go Modules](/using-go-modules) + - **Part 2 — Migrating To Go Modules** (this post) + - Part 3 — [Publishing Go Modules](/publishing-go-modules) + - Part 4 — [Go Modules: v2 and Beyond](/v2-go-modules) Go projects use a wide variety of dependency management strategies. -[[https://golang.org/cmd/go/#hdr-Vendor_Directories][Vendoring]] tools such -as [[https://github.com/golang/dep][dep]] and [[https://github.com/Masterminds/glide][glide]] are popular, +[Vendoring](https://golang.org/cmd/go/#hdr-Vendor_Directories) tools such +as [dep](https://github.com/golang/dep) and [glide](https://github.com/Masterminds/glide) are popular, but they have wide differences in behavior and don't always work well together. Some projects store their entire GOPATH directory in a single Git repository. -Others simply rely on `go`get` and expect fairly recent versions of dependencies +Others simply rely on `go get` and expect fairly recent versions of dependencies to be installed in GOPATH. Go's module system, introduced in Go 1.11, @@ -30,18 +31,18 @@ you will need to update your module path when you add a `go.mod` file. We'll explain how to do that without breaking your users in a future article focused on v2 and beyond. -* Migrating to Go modules in your project +## Migrating to Go modules in your project A project might be in one of three states when beginning the transition to Go modules: -- A brand new Go project. -- An established Go project with a non-modules dependency manager. -- An established Go project without any dependency manager. + - A brand new Go project. + - An established Go project with a non-modules dependency manager. + - An established Go project without any dependency manager. -The first case is covered in [[https://blog.golang.org/using-go-modules][Using Go Modules]]; +The first case is covered in [Using Go Modules](https://blog.golang.org/using-go-modules); we'll address the latter two in this post. -* With a dependency manager +## With a dependency manager To convert a project that already uses a dependency management tool, run the following commands: @@ -77,12 +78,12 @@ To convert a project that already uses a dependency management tool, run the fol require rsc.io/binaryregexp v0.2.1-0.20190524193500-545cabda89ca $ -`go`mod`init` creates a new go.mod file and automatically imports dependencies from `Godeps.json`, -`Gopkg.lock`, or a number of [[https://go.googlesource.com/go/+/362625209b6cd2bc059b6b0a67712ddebab312d9/src/cmd/go/internal/modconv/modconv.go#9][other supported formats]]. -The argument to `go`mod`init` is the module path, +`go mod init` creates a new go.mod file and automatically imports dependencies from `Godeps.json`, +`Gopkg.lock`, or a number of [other supported formats](https://go.googlesource.com/go/+/362625209b6cd2bc059b6b0a67712ddebab312d9/src/cmd/go/internal/modconv/modconv.go#9). +The argument to `go mod init` is the module path, the location where the module may be found. -This is a good time to pause and run `go`build`./...` and `go`test`./...` before continuing. +This is a good time to pause and run `go build ./...` and `go test ./...` before continuing. Later steps may modify your `go.mod` file, so if you prefer to take an iterative approach, this is the closest your `go.mod` file will be to your pre-modules dependency specification. @@ -95,13 +96,13 @@ this is the closest your `go.mod` file will be to your pre-modules dependency sp rsc.io/binaryregexp v0.2.1-0.20190524193500-545cabda89ca/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= $ -`go`mod`tidy` finds all the packages transitively imported by packages in your module. +`go mod tidy` finds all the packages transitively imported by packages in your module. It adds new module requirements for packages not provided by any known module, and it removes requirements on modules that don't provide any imported packages. If a module provides packages that are only imported by projects that haven't migrated to modules yet, -the module requirement will be marked with an `//`indirect` comment. -It is always good practice to run `go`mod`tidy` before committing a `go.mod` +the module requirement will be marked with an `// indirect` comment. +It is always good practice to run `go mod tidy` before committing a `go.mod` file to version control. Let's finish by making sure the code builds and tests pass: @@ -129,10 +130,10 @@ the resulting dependencies. To do so, run and compare the resulting versions with your old dependency management file to ensure that the selected versions are appropriate. If you find a version that wasn't what you wanted, -you can find out why using `go`mod`why`-m` and/or `go`mod`graph`, -and upgrade or downgrade to the correct version using `go`get`. +you can find out why using `go mod why -m` and/or `go mod graph`, +and upgrade or downgrade to the correct version using `go get`. (If the version you request is older than the version that was previously selected, -`go`get` will downgrade other dependencies as needed to maintain compatibility.) For example, +`go get` will downgrade other dependencies as needed to maintain compatibility.) For example, $ go mod why -m rsc.io/binaryregexp [...] @@ -141,7 +142,7 @@ and upgrade or downgrade to the correct version using `go`get`. $ go get rsc.io/binaryregexp@v0.2.0 $ -* Without a dependency manager +## Without a dependency manager For a Go project without a dependency management system, start by creating a `go.mod` file: @@ -157,9 +158,9 @@ For a Go project without a dependency management system, start by creating a `go $ Without a configuration file from a previous dependency manager, -`go`mod`init` will create a `go.mod` file with only the `module` and `go` directives. +`go mod init` will create a `go.mod` file with only the `module` and `go` directives. In this example, we set the module path to `golang.org/x/blog` because that -is its [[https://golang.org/cmd/go/#hdr-Remote_import_paths][custom import path]]. +is its [custom import path](https://golang.org/cmd/go/#hdr-Remote_import_paths). Users may import packages with this path, and we must be careful not to change it. @@ -167,7 +168,7 @@ The `module` directive declares the module path, and the `go` directive declares the expected version of the Go language used to compile the code within the module. -Next, run `go`mod`tidy` to add the module's dependencies: +Next, run `go mod tidy` to add the module's dependencies: $ go mod tidy go: finding golang.org/x/website latest @@ -206,7 +207,7 @@ Next, run `go`mod`tidy` to add the module's dependencies: [...] $ -`go`mod`tidy` added module requirements for all the packages transitively +`go mod tidy` added module requirements for all the packages transitively imported by packages in your module and built a `go.sum` with checksums for each library at a specific version. Let's finish by making sure the code still builds and tests still pass: @@ -222,22 +223,22 @@ Let's finish by making sure the code still builds and tests still pass: ? golang.org/x/blog/support/racy [no test files] $ -Note that when `go`mod`tidy` adds a requirement, +Note that when `go mod tidy` adds a requirement, it adds the latest version of the module. If your `GOPATH` included an older version of a dependency that subsequently published a breaking change, -you may see errors in `go`mod`tidy`, `go`build`, or `go`test`. -If this happens, try downgrading to an older version with `go`get` (for example, -`go`get`github.com/broken/module@v1.1.0`), +you may see errors in `go mod tidy`, `go build`, or `go test`. +If this happens, try downgrading to an older version with `go get` (for example, +`go get github.com/broken/module@v1.1.0`), or take the time to make your module compatible with the latest version of each dependency. -** Tests in module mode +### Tests in module mode Some tests may need tweaks after migrating to Go modules. If a test needs to write files in the package directory, it may fail when the package directory is in the module cache, which is read-only. -In particular, this may cause `go`test`all` to fail. +In particular, this may cause `go test all` to fail. The test should copy files it needs to write to a temporary directory instead. If a test relies on relative paths (`../package-in-another-module`) to locate @@ -252,12 +253,12 @@ If a test expects `go` commands within the test to run in GOPATH mode, it may fa If this is the case, you may need to add a `go.mod` file to the source tree to be tested, or set `GO111MODULE=off` explicitly. -* Publishing a release +## Publishing a release Finally, you should tag and publish a release version for your new module. This is optional if you haven't released any versions yet, but without an official release, downstream users will depend on specific -commits using [[https://golang.org/cmd/go/#hdr-Pseudo_versions][pseudo-versions]], +commits using [pseudo-versions](https://golang.org/cmd/go/#hdr-Pseudo_versions), which may be more difficult to support. $ git tag v1.2.0 @@ -268,31 +269,31 @@ new minimum version requirements. If your users are already using the correct import path, and your dependencies haven't made breaking changes, then adding the `go.mod` file is backwards-compatible — but it's a significant change, and may expose existing problems. If you have existing version tags, you should -increment the [[https://semver.org/#spec-item-7][minor version]]. See -[[/publishing-go-modules][Publishing Go Modules]] to learn how to increment and +increment the [minor version](https://semver.org/#spec-item-7). See +[Publishing Go Modules](/publishing-go-modules) to learn how to increment and publish versions. -* Imports and canonical module paths +## Imports and canonical module paths Each module declares its module path in its `go.mod` file. Each `import` statement that refers to a package within the module must have the module path as a prefix of the package path. However, the `go` command may encounter a repository containing the module -through many different [[https://golang.org/cmd/go/#hdr-Remote_import_paths][remote import paths]]. +through many different [remote import paths](https://golang.org/cmd/go/#hdr-Remote_import_paths). For example, both `golang.org/x/lint` and `github.com/golang/lint` resolve -to repositories containing the code hosted at [[https://go.googlesource.com/lint][go.googlesource.com/lint]]. -The [[https://go.googlesource.com/lint/+/refs/heads/master/go.mod][`go.mod` file]] +to repositories containing the code hosted at [go.googlesource.com/lint](https://go.googlesource.com/lint). +The [`go.mod` file](https://go.googlesource.com/lint/+/refs/heads/master/go.mod) contained in that repository declares its path to be `golang.org/x/lint`, so only that path corresponds to a valid module. -Go 1.4 provided a mechanism for declaring canonical import paths using [[https://golang.org/cmd/go/#hdr-Import_path_checking][`//`import` comments]], +Go 1.4 provided a mechanism for declaring canonical import paths using [`// import` comments](https://golang.org/cmd/go/#hdr-Import_path_checking), but package authors did not always provide them. As a result, code written prior to modules may have used a non-canonical import path for a module without surfacing an error for the mismatch. When using modules, the import path must match the canonical module path, so you may need to update `import` statements: -for example, you may need to change `import`"github.com/golang/lint"` to -`import`"golang.org/x/lint"`. +for example, you may need to change `import "github.com/golang/lint"` to +`import "golang.org/x/lint"`. Another scenario in which a module's canonical path may differ from its repository path occurs for Go modules at major version 2 or higher. @@ -304,15 +305,15 @@ For example, non-module users of `github.com/russross/blackfriday/v2` at `v2.0.1` may have imported it as `github.com/russross/blackfriday` instead, and will need to update the import path to include the `/v2` suffix. -* Conclusion +## Conclusion Converting to Go modules should be a straightforward process for most users. Occasional issues may arise due to non-canonical import paths or breaking changes within a dependency. -Future posts will explore [[/publishing-go-modules][publishing new versions]], +Future posts will explore [publishing new versions](/publishing-go-modules), v2 and beyond, and ways to debug strange situations. To provide feedback and help shape the future of dependency management in Go, -please send us [[https://golang.org/issue/new][bug reports]] or [[https://golang.org/wiki/ExperienceReports][experience reports]]. +please send us [bug reports](https://golang.org/issue/new) or [experience reports](https://golang.org/wiki/ExperienceReports). Thanks for all your feedback and help improving modules. |