这是我参与「第五届青训营 」伴学笔记创作活动的第 12 天
背景
在家安装的环境可能路径和环境变量配的有些问题,导致项目import的包全部标红,go mod tidy显示导入包不在路径,怎么可能不在路径呢。
这就好比我们写cpp程序,我们从官方库里include一个.h,而后自己图方便也写了个.h,但是程序并不能识别出我们自己写的.h,并反问我们这个.h为什么不在官方的包里。exm..
那肯定是路径错了,设置来设置去也没解决。
原因可能是因为不熟悉linux操作,半途没保存导致没配成功,但还是跑出hello world导致我以为自己PATH对了。费尽心思改来改去,找依赖的路径,找了两天,最后得出结论——安装目录就已经乱了。遂打算重装。接下来的笔记大概是记录重装过程&常用的操作合集,算是补充了第一篇笔记遗留的还没写的东西。
为了解决包的问题,go mod tidy建议我进行go mod vendor,果然不报错了,可是文件夹下多了1k多的变化,是他根据我的包定义的空包以及一些外部包导到项目目录的下载,只能解决编译报错问题,根本不能对项目有任何作用。后来才了解到go vendor早就已经不适用,早年1.13版本之前,go mod还未成熟,使用起来不太方便。 开发的时候还是需要go get
提前下载包,然后再应用。 只有要打包的时候执行一套命令,类似于下面这样:
go mod init ./
go build main.go 或 go build -mod=vendor main.go
go mod vendor #将包打到vendor文件夹下
Go Vendor
安装go get -u github.com/kardianos/govendor
基础命令
govendor init # 创建vendor目录,创建vendor.json文件
govendor add +external #生成依赖包
govendor update +vendor # 更新vendor的包命令
init 初始化 vendor 目录
list 列出所有的依赖包
add 添加包到 vendor 目录,如 govendor add +external 添加所有外部包
add PKG_PATH 添加指定的依赖包到 vendor 目录
update 从 $GOPATH 更新依赖包到 vendor 目录
remove 从 vendor 管理中删除依赖
status 列出所有缺失、过期和修改过的包
fetch 添加或更新包到本地 vendor 目录
sync 本地存在 vendor.json 时候拉去依赖包,匹配所记录的版本
get 类似 go get 目录,拉取依赖包到 vendor 目录
Go Mod
go module是Go1.11版本之后官方推出的版本管理工具,并且从Go1.13版本开始,go module将是Go语言默认的依赖管理工具
modules是源代码交换和版本控制的单元。 go命令直接支持使用modules,包括记录和解析对其他模块的依赖性。modules替换旧的基于GOPATH的方法来指定在给定构建中使用哪些源文件。
要启用go module支持首先要设置环境变量GO111MODULE,通过它可以开启或关闭模块支持,它有三个可选值:off、on、auto,默认值是auto。
GO111MODULE=off禁用模块支持,编译时会从GOPATH和vendor文件夹中查找包。
GO111MODULE=on启用模块支持,编译时会忽略GOPATH和vendor文件夹,只根据 go.mod下载依赖。
GO111MODULE=auto,当项目在$GOPATH/src外且项目根目录有go.mod文件时,开启模块支持。
启用 Go Modules 功能
export GO111MODULE=on
基础命令
go mod download 下载依赖的module到本地cache(默认为$GOPATH/pkg/mod目录)
go mod edit 编辑go.mod文件
go mod graph 打印模块依赖图
go mod init 初始化当前文件夹, 创建go.mod文件
go mod tidy 增加缺少的module,删除无用的module
go mod vendor 将依赖复制到vendor下
go mod verify 校验依赖
go mod why 解释为什么需要依赖
新建项目中使用
在GOPATH 目录之外
新建一个目录,并使用go mod init
初始化生成go.mod
文件
➜ ~ mkdir hello
➜ ~ cd hello
➜ hello go mod init hello
go: creating new go.mod: module hello
➜ hello ls
go.mod
➜ hello cat go.mod
module hello
go.mod文件一旦创建后,它的内容将会被go toolchain全面掌控。go toolchain会在各类命令执行时,比如go get、go build、go mod等修改和维护go.mod文件。
go.mod 提供了module
, require
、replace
和exclude
四个命令
module
语句指定包的名字(路径)require
语句指定的依赖项模块replace
语句可以替换依赖项模块exclude
语句可以忽略依赖项模块
添加依赖->执行go run->go mod 会自动查找依赖自动下载->查看go mod
只管加依赖,然后go mod tidy,可以理解为go mod是自动生成的。
go module 安装 package 原则
go module 安装 package 原则是先拉最新的 release tag,若无tag则拉最新的commit,详见 Modules官方介绍。 go 会自动生成一个 go.sum 文件来记录 dependency tree:
# 查看dependency tree
$ cat go.sum
再次执行脚本 go run
发现跳过了检查并安装依赖的步骤。
可以使用命令 go list -m -u all
来检查可以升级的package,使用go get -u need-upgrade-package
升级后会将新的依赖版本更新到go.mod
也可以使用 go get -u
升级所有依赖
使用 go get -u 升级所有依赖
- 运行 go get -u 将会升级到最新的次要版本或者修订版本(x.y.z, z是修订版本号, y是次要版本号)
- 运行 go get -u=patch 将会升级到最新的修订版本
- 运行 go get package@version 将会升级到指定的版本号version
- 运行go get如果有版本的更改,那么go.mod文件也会更改
改造已有项目
- 使用
go mod init
初始化go.mod - 运行
go run
, go.mod会更新
查找并下载安装依赖后会报错cmd/go: 'cannot find module for path' when importing from subdirectories · Issue #26645 · golang/go (github.com)
解决:更新旧的package import 方式
原因:使用 internal package 的方法跟以前不同,go.mod会扫描同工作目录下所有 package 并且变更引入方法,必须将(当前工作文件)当成路径的前缀,需要写成 import xxx/api,以往GOPATH/dep模式允许的 import ./api 已经失效
使用replace替换无法直接获取的package
由于某些已知的原因,并不是所有的package都能成功下载,比如:golang.org
下的包。
modules 可以通过在 go.mod 文件中使用 replace 指令替换成github上对应的库
Go1.14版本vendor和go module冲突问题
go1.14版本使用go mod tidy构建依赖时会出现问题(见链接), 这个问题在go1.12版本是不会出现的.
这是由于1.14版本官方加入了校验机制导致的,
解决:
- 使用低版本的go, 但更推荐第二种方法.
- 删除自带vendor重建依赖
项目文件夹下不能有vendor目录。除非是go mod vendor生成的
# 1. 删除vendor文件夹
mv vendor ${GOPATH}
# 2. 重新replace本地依赖, 指向${GOPATH}/vendor
vim go.mod
# 3. 重建依赖
go mod tidy
# 4. 生成vendor, 可做可不做
go mod vendor
标签:12,vendor,get,module,依赖,go,mod
From: https://www.cnblogs.com/peace0218/p/17070557.html