目录

  • 1. 版权
  • 2. 原文
    • Introduction
    • Migrating to Go modules in your project
    • With a dependency manager
    • Without a dependency manager
    • Tests in module mode
    • Publishing a release
    • Imports and canonical module paths
    • Conclusion
  • 3. 笔记

1. 版权

按https://golang.org/doc/copyright.html, 原文内容使用 Creative Commons Attribution 3.0 License, 代码使用 BSD license.

使用原文之外的部分, 需注明出处: https://blog.csdn.net/big_cheng/article/details/107339941.

2. 原文

Migrating to Go Modules
Jean de Klerk
21 August 2019

Introduction

This post is part 2 in a series.

  • Part 1 — Using Go Modules
  • Part 2 — Migrating To Go Modules (this post)
  • Part 3 — Publishing Go Modules
  • Part 4 — Go Modules: v2 and Beyond
  • Part 5 - Keeping Your Modules Compatible

Go projects use a wide variety of dependency management strategies. Vendoring tools such as dep and 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 to be installed in GOPATH.

Go’s module system, introduced in Go 1.11, provides an official dependency management solution built into the go command. This article describes tools and techniques for converting a project to modules.

Please note: if your project is already tagged at v2.0.0 or higher, 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

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.

The first case is covered in Using Go Modules; we’ll address the latter two in this post.

With a dependency manager

To convert a project that already uses a dependency management tool, run the following commands:

$ git clone https://github.com/my/project
[...]
$ cd project
$ cat Godeps/Godeps.json
{"ImportPath": "github.com/my/project","GoVersion": "go1.12","GodepVersion": "v80","Deps": [{"ImportPath": "rsc.io/binaryregexp","Comment": "v0.2.0-1-g545cabd","Rev": "545cabda89ca36b48b8e681a30d9d769a30b3074"},{"ImportPath": "rsc.io/binaryregexp/syntax","Comment": "v0.2.0-1-g545cabd","Rev": "545cabda89ca36b48b8e681a30d9d769a30b3074"}]
}
$ go mod init github.com/my/project
go: creating new go.mod: module github.com/my/project
go: copying requirements from Godeps/Godeps.json
$ cat go.mod
module github.com/my/projectgo 1.12require 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 other supported formats. 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. 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.

$ go mod tidy
go: downloading rsc.io/binaryregexp v0.2.1-0.20190524193500-545cabda89ca
go: extracting rsc.io/binaryregexp v0.2.1-0.20190524193500-545cabda89ca
$ cat go.sum
rsc.io/binaryregexp v0.2.1-0.20190524193500-545cabda89ca h1:FKXXXJ6G2bFoVe7hX3kEX6Izxw5ZKRH57DFBJmHCbkU=
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. 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 file to version control.

Let’s finish by making sure the code builds and tests pass:

$ go build ./...
$ go test ./...
[...]
$

Note that other dependency managers may specify dependencies at the level of individual packages or entire repositories (not modules), and generally do not recognize the requirements specified in the go.mod files of dependencies. Consequently, you may not get exactly the same version of every package as before, and there’s some risk of upgrading past breaking changes. Therefore, it’s important to follow the above commands with an audit of the resulting dependencies. To do so, run

$ go list -m all
go: finding rsc.io/binaryregexp v0.2.1-0.20190524193500-545cabda89ca
github.com/my/project
rsc.io/binaryregexp v0.2.1-0.20190524193500-545cabda89ca
$

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. (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 mod why -m rsc.io/binaryregexp
[...]
$ go mod graph | grep rsc.io/binaryregexp
[...]
$ go get rsc.io/binaryregexp@v0.2.0
$

Without a dependency manager

For a Go project without a dependency management system, start by creating a go.mod file:

$ git clone https://go.googlesource.com/blog
[...]
$ cd blog
$ go mod init golang.org/x/blog
go: creating new go.mod: module golang.org/x/blog
$ cat go.mod
module golang.org/x/bloggo 1.12
$

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. In this example, we set the module path to golang.org/x/blog because that is its custom import path. Users may import packages with this path, and we must be careful not to change it.

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:

$ go mod tidy
go: finding golang.org/x/website latest
go: finding gopkg.in/tomb.v2 latest
go: finding golang.org/x/net latest
go: finding golang.org/x/tools latest
go: downloading github.com/gorilla/context v1.1.1
go: downloading golang.org/x/tools v0.0.0-20190813214729-9dba7caff850
go: downloading golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7
go: extracting github.com/gorilla/context v1.1.1
go: extracting golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7
go: downloading gopkg.in/tomb.v2 v2.0.0-20161208151619-d5d1b5820637
go: extracting gopkg.in/tomb.v2 v2.0.0-20161208151619-d5d1b5820637
go: extracting golang.org/x/tools v0.0.0-20190813214729-9dba7caff850
go: downloading golang.org/x/website v0.0.0-20190809153340-86a7442ada7c
go: extracting golang.org/x/website v0.0.0-20190809153340-86a7442ada7c
$ cat go.mod
module golang.org/x/bloggo 1.12require (github.com/gorilla/context v1.1.1golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7golang.org/x/text v0.3.2golang.org/x/tools v0.0.0-20190813214729-9dba7caff850golang.org/x/website v0.0.0-20190809153340-86a7442ada7cgopkg.in/tomb.v2 v2.0.0-20161208151619-d5d1b5820637
)
$ cat go.sum
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
git.apache.org/thrift.git v0.0.0-20181218151757-9b75e4fe745a/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
[...]
$

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:

$ go build ./...
$ go test ./...
ok      golang.org/x/blog   0.335s
?       golang.org/x/blog/content/appengine [no test files]
ok      golang.org/x/blog/content/cover 0.040s
?       golang.org/x/blog/content/h2push/server [no test files]
?       golang.org/x/blog/content/survey2016    [no test files]
?       golang.org/x/blog/content/survey2017    [no test files]
?       golang.org/x/blog/support/racy  [no test files]
$

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), or take the time to make your module compatible with the latest version of each dependency.

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. 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 and read files in another package, it will fail if the package is in another module, which will be located in a versioned subdirectory of the module cache or a path specified in a replace directive. If this is the case, you may need to copy the test inputs into your module, or convert the test inputs from raw files to data embedded in .go source files.

If a test expects go commands within the test to run in GOPATH mode, it may fail. 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

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 pseudo-versions, which may be more difficult to support.

$ git tag v1.2.0
$ git push origin v1.2.0

Your new go.mod file defines a canonical import path for your module and adds 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 minor version. See Publishing Go Modules to learn how to increment and publish versions.

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 remote import paths. For example, both golang.org/x/lint and github.com/golang/lint resolve to repositories containing the code hosted at go.googlesource.com/lint. The go.mod file 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 // import comments, 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”.

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. A Go module with a major version above 1 must include a major-version suffix in its module path: for example, version v2.0.0 must have the suffix /v2. However, import statements may have referred to the packages within the module without that suffix. 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

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 new versions, 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 bug reports or experience reports.

Thanks for all your feedback and help improving modules.

3. 笔记

原有的工具如dep, glide.

项目原来已经有依赖管理工具时:
go mod init会自动导入原工具管理的依赖.
go mod tidy: 递归添加依赖、删除未用的模块依赖、添加indirect依赖(仅被非模块项目依赖).
go build和go test.
检查依赖状况: go list -m all、go mod why -m xxx、go mod graph. 用go get 升降级.

项目原来未使用依赖管理工具时:
go mod init 模块路径(module path).
go mod tidy 递归添加依赖.
go build和go test.
由于go mod tidy添加的是最新版本, 导致兼容错误时go get升降级、或调整项目自身代码.

如果原测试代码需读、写包路径下的文件, 由于go模块的包缓存位置已变, 需要移动位置或改写到临时目录等.

不同的导入路径(import path) 例如"golang.org/x/lint" 和"github.com/golang/lint" 可指向同一个代码仓库如go.googlesource.com/lint - 该仓库的go.mod里定义的路径"golang.org/x/lint" 才是规范的模块路径(canonical module path).
使用go模块后, import path必须以canonical module path 开头 (不能再写 import “github.com/golang/lint” 了).
另, 从主版本2开始模块路径必须以"/v2、/v3、…" 结尾.

GolangBlog ModuleSeries - Part 2 | Migrating to Go Modules相关推荐

  1. Part 3 —— 发布 Go Modules

    文章目录 简介(Introduction) 项目设置(Project setup) 语义版本和模块(Semantic versions and modules) v0:最初的不稳定版本(v0: the ...

  2. Part 2 —— 迁移到 Go Modules

    文章目录 简介 将项目迁移至 Go modules 使用依赖管理器 没有依赖管理器 模块模式下的测试 发布发行版 导入和规范模块路径 结论 相关文章 参考文献 简介 翻译自 Go 官方博文 Migra ...

  3. Part 1——使用 Go Modules

    文章目录 简介 创建新模块 添加依赖项 升级依赖项 使用新主版本的依赖项 将依赖项升级到新的主要版本 删除未使用的依赖项 结论 相关文章 翻译自 Go 官方博文 Using Go Modules. T ...

  4. webpack5不要再用url-loader了

    webpack 最出色的功能之一就是,除了引入 JavaScript,还可以通过 loader 或内置的 Asset Modules 引入任何其他类型的文件. webpack5 新增 Asset Mo ...

  5. 保持 Go 模块兼容

    简介(Introduction) 翻译自 Go 官方博文 Keeping Your Modules Compatible. Jean de Klerk and Jonathan Amsterdam 7 ...

  6. Part 4 —— Go 模块:v2 及更高版本

    文章目录 简介(Introduction) 主要版本和模块路径(Major versions and module paths) 主要版本策略(Major version strategies) 发布 ...

  7. Go 工程化标准实践

    本文参考 Go 微服务框架 go-kratos/kratos 的项目结构及相关最佳实践,Kratos 一套轻量级 Go 微服务框架,包含大量微服务相关功能及工具. 项目结构 标准项目结构 /cmd | ...

  8. CSS Modules

    css-loader 提供了一种叫做 CSS Modules 的方案,可以帮我们自动生成唯一的类名,不会和其他模块的命名出现冲突 要使用 CSS Modules 有几个步骤,首先需要在 webpack ...

  9. modules黑名单

    http://www.linuxsir.org/bbs/thread321140.html 今天刚看了udev的资料,说可以用blacklist禁用掉, 写在/etc/modules.d/blackl ...

最新文章

  1. atom配置python环境_Win10如何配置Python的环境变量
  2. python内置函数open_Python的内置函数open()的注意事项
  3. 如何多次读取request请求里的数据
  4. 『 Luogu P3205 』 HNOI2010 合唱队
  5. 如何显示内存中的 HTML 网页
  6. ES6-类-ES6新增的类的概念
  7. 心语收集8:若无缘,与之言多,亦废。若有缘,你的存在,就能惊醒他所有的感觉。...
  8. Leetcode 105. 前序和中序遍历序列构造二叉树
  9. 基于 Flink、ClickHouse 的舆情分析系统:系统架构设计说明书
  10. Python如何出矢量图
  11. 微软笔记本服务器怎么重装系统,微软Surface Book重装win10系统教程
  12. 20162327WJH使用队列:模拟票务站台代码分析
  13. html怎么设置后退链接,怎么创建HTML后退按钮?
  14. win7系统无法开启telnet服务器,Win7系统开启telnet客户端解决无法使用命令问题
  15. Stata:固定效应模式必须加入时间固定效应吗?
  16. 电子商务系统需求分析
  17. 轻触开源(二)-Gson项目源码解析_壹
  18. Springboot+Mybatis-plus实现增删改查功能超详细
  19. k8s之PV以及PVC
  20. 雾里看花般的迷茫--货运APP

热门文章

  1. 数据库设计——医药销售管理系统
  2. [附源码]java毕业设计幼儿园管理系统
  3. jumbo frame介绍
  4. 飞冰(ICE) 阿里家的前端图形化一键工具
  5. 联想电脑,Windows11系统,键盘突然无法输入
  6. OpenCV + OpenCV Contrib安装教程(windows)
  7. CTFshow刷题日记-MISC-图片篇(上)基础操作和信息附加
  8. 使用OpenCV进行图像修复、Navier-Stokes、INPAINT_TELEA,专栏:各种openCV实践的案例
  9. 基因预测软件-Augustus安装过程
  10. Android10连接WiFi的方法