Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >GOPATH 模式怎么迁移至 Modules 模式?

GOPATH 模式怎么迁移至 Modules 模式?

作者头像
frank.
发布于 2020-11-12 07:14:17
发布于 2020-11-12 07:14:17
2.2K00
代码可运行
举报
运行总次数:0
代码可运行

01

介绍

Go 项目使用多种依赖管理策略。诸如 dep 和 glide 很受欢迎,但是它们在使用上有很大差异,并且并不总是能很好地协同工作。某些项目将其整个 GOPATH 目录存储在单个 Git 存储库中。其他人只是依靠 go get 获取,并期望在 GOPATH 中安装相当新版本的依赖项。

在 Go 1.11 中引入 Go 的模块系统,它提供了内置于 go 命令中的官方依赖管理解决方案。本文介绍将项目转换为 Modules 模式的工具和技术。

请注意:如果您的项目已在 v2.0.0 或更高版本标记,则需要在添加 go.mod 文件时更新模块路径。因为 Go modules 的每个不同主要版本(v1、v2 等)使用不同的模块路径:从 v2 开始,路径必须以主要版本结束。

02

迁移至 Modules 模式

在开始过渡到 Go Modules 时,项目可能为三种状态之一:

  • 一个全新的 Go 项目。
  • 具有非模块依赖管理工具的已建立的 Go 项目。
  • 没有任何依赖项管理工具的已建立的 Go 项目。

第一种状态已在「Go Modules 介绍与基本操作」中介绍;我们将在这篇文章中讨论后两种。

03

已使用依赖管理工具的项目

若要转换已使用依赖项管理工具的项目,请运行以下命令:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ 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/project

go 1.12

require rsc.io/binaryregexp v0.2.1-0.20190524193500-545cabda89ca
$

go mod init 创建一个新的 go.mod 文件,并自动从 Godeps.json、Gopkg.lock 或一些其他受支持的格式导入依赖项。go mod init 的参数是模块路径,即可能找到模块的目录位置。

在继续之前,这是一个暂停并运行 go build ./... 和 go test ./... 的最佳时间。后续的步骤可能会修改您的 go.mod 文件,因此如果您喜欢采用迭代方法,这是最接近您的预模块依赖项规范的 go.mod 文件。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ 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 查找模块中导入的所有包。它为任何已知模块未提供的包添加新的模块依赖,并删除不提供任何导入包的模块依赖。如果模块提供的包仅由尚未迁移到模块的项目导入,则模块要求将用 // indirect 注释进行标记。在将 go.mod 文件提交到版本控制之前运行 go mod tidy 始终是一种好的做法。

通过成功运行 go build 和 go test 确保代码正确。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ go build ./...
$ go test ./...
[...]
$

请注意,其他依赖项管理工具可能在单个包或整个存储库(不是模块)级别指定依赖项,并且通常不识别依赖项的 go.mod 文件中指定的要求。因此,您可能不会获得与以前完全相同的每个包版本,并且存在升级过去中断更改的风险。因此,对生成的依赖项进行审核时遵循上述命令非常重要。为此,请运行

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ 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
$

查看依赖项列表,并将生成的版本与旧的依赖项管理文件进行比较,以确保所选版本是适当的。如果你找到一个版本,不是你想要的,你可以运行 go mod why -m 和/或 go mod graph 查看,并使用 go get 升级或降级到正确的版本。(如果您请求的版本比以前选择的版本要旧,则 go get 将根据需要降级其他依赖项以保持兼容性。)

示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ go mod why -m rsc.io/binaryregexp
[...]
$ go mod graph | grep rsc.io/binaryregexp
[...]
$ go get rsc.io/binaryregexp@v0.2.0
$

04

未使用依赖管理工具的项目

对于未使用依赖项管理工具的 Go 项目,首先创建 go.mod 文件:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ 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/blog

go 1.12
$

如果没有来自以前依赖项管理工具的配置文件,go mod init 将创建一个仅包含模块和 go 指令的 go.mod 文件。在此示例中,我们将模块路径设置为golang.org/x/blog 因为这是其自定义导入路径。用户可以使用此路径导入包,我们必须注意不要更改它。

模块指令声明模块路径,go 指令声明用于编译模块内代码的 Go 语言的预期版本。

接下来,运行 go mod tidy 以添加模块的依赖项:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ 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/blog

go 1.12

require (
    github.com/gorilla/context v1.1.1
    golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7
    golang.org/x/text v0.3.2
    golang.org/x/tools v0.0.0-20190813214729-9dba7caff850
    golang.org/x/website v0.0.0-20190809153340-86a7442ada7c
    gopkg.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 添加了模块中包传输导入的所有包的模块依赖,并在特定版本上为每个库构建了一个 go.sum,其中包含每个库的校验。

通过成功运行 go build 和 go test 确保代码正确。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ 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]
$

请注意,当 go mod tidy 添加依赖时,它会添加模块的最新版本。如果您的 GOPATH 包含后来发布中断更改的依赖项的较旧版本,您可能会在 go mod tidy、go build 或 go test 中看到错误。如果发生这种情况,请尝试使用 go get 降级到旧版本(例如,

go get github.com/broken/module@v1.1.0 ),或花一些时间使您的模块与每个依赖项的最新版本兼容。

05

在模块模式下测试

迁移到 Go 模块后,某些测试可能需要进行调整。如果测试需要在程序包目录中写入文件,则当程序包目录位于 module cache 时(只读),它可能会失败。特别是,这可能会导致全部测试失败。测试应将需要写入的文件复制到临时目录中。

如果测试依赖于相对路径(../package-in-another-module)来定位和读取另一个软件包中的文件,则该测试将失败,如果该软件包位于另一个模块中,则该模块位于该模块的版本子目录中的 module cache 或替换指令(replace)中指定的路径。在这种情况下,您可能需要将测试输入复制到模块中,或将测试输入从原始文件转换为嵌入在 .go 源文件中的数据。

如果测试期望测试中的 go 命令以 GOPATH 模式运行,则可能会失败。在这种情况下,您可能需要将 go.mod 文件添加到要测试的源树中,或显式设置GO111MODULE = off。

06

发布发行版本

最后,您应该标记(git tag vx.x.x)并发布新模块的发行版本(git push origin vx.x.x)。如果您尚未发布任何版本,但是这是可选的,但是如果没有正式发布,则下游用户将依赖使用伪版本的特定提交,这可能更难支持。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ git tag v1.2.0
$ git push origin v1.2.0

新的 go.mod 文件为模块定义了规范的导入路径,并添加了新的最低版本要求。如果您的用户已经在使用正确的导入路径,并且您的依赖项尚未进行重大更改,则添加go.mod文件是向后兼容的-但这是一项重大更改,并且可能会暴露现有问题。如果有现有的版本标签,则应增加次要版本。

07

导入和规范的模块路径

每个模块在其 go.mod 文件中声明其模块路径。每个引用模块内包的 import语句必须将模块路径作为包路径的前缀。但是,go 命令可能会通过许多不同的远程导入路径遇到同一个包含模块的存储库。例如,golang.org/x/lint 和github.com/golang/lint 都解析为包含 go.googlesource.com/lint 上托管代码的存储库。该存储库中包含的 go.mod 文件将其路径声明为golang.org/x/lint,因此仅该路径对应于有效模块。

Go 1.4提供了一种使用 // import comments,声明规范导入路径的机制,但是包作者并不总是提供它们。结果,在模块之前编写的代码可能已经为模块使用了非规范的导入路径,而没有出现不匹配的错误。使用模块时,导入路径必须与规范的模块路径匹配,因此您可能需要更新导入语句:例如,您可能需要将导入

“github.com/golang/lint”

更改为导入“golang.org/x/lint”。

在主要版本 2 或更高版本的Go模块中,发生模块的规范路径可能不同于其存储库路径的另一种情况。主版本高于 1 的 Go 模块的模块路径中必须包含主版本后缀:例如,版本 v2.0.0 必须具有后缀/v2。但是,import 语句可能已经引用了没有该后缀的模块中的软件包。

例如,版本为 v2.0.1 的

github.com/russross/blackfriday/v2

的非模块用户可能已将其导入为

github.com/russross/blackfriday,该情况下,将需要更新导入路径以包含 /v2 后缀。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-11-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Go语言开发栈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
迁移到 Go Modules
Go 项目使用多种依赖管理策略,其中对 vendor 包的管理有两个比较流行的工具 dep 和 glide,但他们在行为上有很大的差异,而且并不是总能很好地同时使用。一些项目将其整个 GOPATH 目录存储在一个 Git 仓库中。其他人则只依赖于 go get 并期望在GOPATH中安装较新版本的依赖项。
恋喵大鲤鱼
2020/09/08
8520
Go 模块--开始使用Go Modules
Go的1.11和1.12版本包括对模块--新的Go依赖管理系统的初步支持,使依赖版本信息变得明确且更易于管理。这篇博客文章介绍了开始使用模块所需的基本操作。
KevinYan
2020/01/14
2.6K0
2019年8月21日 Go生态洞察:迁移到Go模块
🐯 嗨,猫头虎博主在此!今天我们将探索2019年8月21日发布的Go生态系列文章的第二部分,专注于迁移到Go模块。Go模块是Go 1.11中引入的官方依赖管理解决方案,本文将详细介绍如何将项目转换为模块。无论您是初次接触Go模块还是寻求深入理解,这篇文章都将为您提供宝贵的洞见。🔍
猫头虎
2024/04/08
1100
2019年8月21日 Go生态洞察:迁移到Go模块
发布 Go Modules
请注意:这篇文章涵盖了 v1 及其之前的开发,如果您对 v2 感兴趣,请参阅 Go Modules: v2 and Beyond。
恋喵大鲤鱼
2020/09/16
7770
Go Modules 详解
Go 1.11 和 Go 1.12 包含了初步的 Go Modules 支持,且计划在 2019 年 8 月发布的 Go 1.13 会在所有开发过程中默认使用 Go Modules。
码农编程进阶笔记
2021/07/20
8750
Go Modules 详解
Go语言重新开始,Go Modules的前世今生与基本使用
2020年腾讯内部的一份开发者报告显示,Go语言已经成为腾讯内部第二大后端开发语言,在腾讯每天有大量的Go开发者在做业务和平台开发,大量的团队和项目使用也暴露出一些问题,随着Go Modules的出现,类似于内部自签发证书、安全审计等这些问题也逐渐得到解决。 笔者在腾讯当前负责腾讯云在Go编程语言使用上的一些问题,2021年初开始负责内部goproxy服务并推广Go Modules使用,这些技术支撑了腾讯云、微信、腾讯视频、腾讯游戏、腾讯音乐、腾讯会议等明星产品,并与公司内部软件源团队、工蜂团队、
腾讯云开发者
2021/11/25
6730
Go语言重新开始,Go Modules 的前世今生与基本使用
2020 年腾讯内部的一份开发者报告显示,Go 语言已经成为腾讯内部第二大后端开发语言,在腾讯每天有大量的 Go 开发者在做业务和平台开发,大量的团队和项目使用也暴露出一些问题,随着 Go Modules 的出现,类似于内部自签发证书、安全审计等这些问题也逐渐得到解决。
Bain
2021/11/02
7970
Go语言重新开始,Go Modules 的前世今生与基本使用
Go编程之相关命令工具记录
该命令可以借助代码管理工具通过远程拉取或更新代码包及其依赖包,并自动完成编译和安装,整个过程类似安装App一样;
全栈工程师修炼指南
2022/09/29
6280
Go mod的简单实践
Go mod简介: Go mod是官方推荐的包管理方式,开始于go1.11,在go1.12版本基本稳定,go1.13之后开始默认开启。
灰子学技术
2020/05/20
10.5K0
Golang中的包管理工具 - Go Modules
在Go1.5之前使用GOROOT和GOPATH这2个系统环境变量来决定包的位置,对于开发者主要使用GOPATH。GOPATH 解决了第三方源码依赖的问题,看一下我本机 $GOPATH/src 下的目录:
猿哥
2019/08/01
1.6K0
Go modules基础精进,六大核心概念全解析(下)
在上篇中,我们介绍了模块路径、版本号与兼容性原则、伪版本号三大概念,而在下篇我们将会继续介绍Go Modules核心概念。
Bain
2021/12/06
7220
Go modules基础精进,六大核心概念全解析(下)
2019年3月19日 Go生态洞察:使用Go模块
🐆 猫头虎博主来了!今天,我们将探索Go语言的一个重要特性——Go模块。在这篇文章中,我将深入解析Go模块的使用方法,并提供一些实际的代码示例。如果你正在搜索如何有效管理Go项目的依赖关系,那么你来对地方了!让我们一起深入Go的世界,探索其模块化的魅力!🚀
猫头虎
2024/04/08
1220
2019年3月19日 Go生态洞察:使用Go模块
GoLang 新版包管理 -- go module 的使用
上一篇文章中,我们介绍了 GoLang 中包的使用与包管理机制。 GoLang 包的使用与管理
用户3147702
2022/06/27
2.4K0
GoLang 新版包管理 -- go module 的使用
Go 1.11 相比 Go 1.10 有哪些值得注意的改动?
Go 1.11 版本引入了对 Go 模块 (Go Modules) 的初步支持,这是 Go 语言在包管理和版本依赖方面的一个重大变革,旨在解决长期以来 GOPATH 模式带来的诸多问题。Modules 提供了一种新的方式来管理项目依赖,集成了版本控制和包分发功能,使得开发者可以:
Piper破壳
2025/04/21
730
Go 编程 | 连载 21 - Go Modules 和 Package
GOPATH 是 Go 语言中使用的一个环境变量,它使用绝对路径提供项目的共工作目录,GOPATH 适合处理大量 Go 语言源码、多个包组合而成的复杂工程。
RiemannHypothesis
2022/09/28
5200
Go的包管理工具(三):Go Modules
在前面的文章,我们先是介绍了Go 的几种包管理方式,然后具体介绍了一种包管理的工具:glide。随着 Go 1.11 的发布,官方的包管理工具 Go Modules 变得流行起来。在发布不久的 Go 1.12 版本中,增强了对 Go Modules 的支持。本文将会介绍如何在项目中安装和使用 Go Modules 。
aoho求索
2019/05/07
1.5K0
Go Modules 终极入门
Go modules 是 Go 语言中正式官宣的项目依赖解决方案,Go modules(前身为vgo)于 Go1.11 正式发布,在 Go1.14 已经准备好,并且可以用在生产上(ready for production)了,Go 官方也鼓励所有用户从其他依赖项管理工具迁移到 Go modules。
madneal
2020/03/10
1.9K0
Go Modules 终极入门
跳出Go module的泥潭
Go 1.11 前天已经正式发布了,这个版本包含了两个最重要的feature就是 module和web assembly。虽然也有一些简单的教程介绍了go module的特性,但是基本上都是hello world的例子,在实践的过程中, 很多人都在“拼命的挣扎”,包括我自己, 从一些qq群、github的issue, twitter上都可以看到大家茫然或者抱怨的语句。
李海彬
2018/09/29
1.7K0
跳出Go module的泥潭
GO 依赖管理工具go Modules(官方推荐)
以前写过一篇关于go管理依赖包工具 dep的文章,当时认为dep将会成为官方依赖工具,现在看来是自己图样图斯内幕破了,正如官方一直提到dep是“official experiment”官方实验项目的那样,随着go modules 在go1.11版推出,go1.12版功能不断改进,再到go1.13版完善优化,正式扶正。预计dep将来也只能定格在“official experiment”了。
孤烟
2020/09/27
1.8K1
Go包管理工具
想想Java的Maven, Nodejs的NPM,还有我们赞颂一万遍也不过分的Python包管理,为什么生命总要浪费在这些事情上面呢? 陷入了深深的沉思~~
happy123.me
2019/12/30
7000
相关推荐
迁移到 Go Modules
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验