gomodule管理
https://cloud.tencent.com/developer/article/1818131
[Go]解决goland terminal 环境变量不更新
在自己的电脑修改了PATH环境变量 , 但是goland terminal不更新
goland只在开机启动的时候会去读取系统的PATH环境变量
1.可以重启电脑解决
2.手动在terminal中设置一下PATH (win10 的path全都分开了, 不方便, 只用一个设置不起作用
参考;https://cloud.tencent.com/developer/article/1502469?from=article.detail.1818131
下面这个例子是依赖github.com/sirupsen/logrus 输出一行日志。在GOPATH外创建一个mytest的目录,然后创建一个main.go的文件,内容如下
package main
import (
log "github.com/sirupsen/logrus"
)
func main() {
// Add this line for logging filename and line number!
log.SetReportCaller(true)
log.Println("hello world")
}
open termal: 执行
go mod init mytest
其实mytest是我指定的module名称,可以是任意的命名,但是一定要指定,否则会报错 go: cannot determine module path for source directory。
然后执行go build就会成功编译,并且多了go.mod和go.sum两个module相关的文件:(如果没有go.sun以及go.mod的依赖包中没有列出main.go中导入的包,则说明当前GOPATH/pkg/mod/ 中没有需要的包)
再go build 进行编译,如果编译失败,并报错 main.go:5:2: no required module provides package github.com/urfave/cli; to add it: github.com/sirupsen/logrus
那就go get github.com/sirupsen/logrus, 之后会在当前GOPATH/pkg/mod/ 中多出 github.com/sirupsen/logrus的包, go.mod文件的依赖完整了, go.sum文件有了
此时再go build 就ok了
然后执行go build就会成功编译,并且多了go.mod和go.sum两个module相关的文件:
$ ls
go.mod go.sum main.go mytest
$ cat go.mod
module mytest
go 1.12
require github.com/sirupsen/logrus v1.4.2
$ cat go.sum
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
从示例中可以看出go.mod文件存放的是工程包依赖信息,而go.sum里面存放的是依赖包的校验信息。主要关注go.mod的信息。可以看到,如果我们不指定依赖包的版本信息,go build默认是会替我们去拉取该依赖包的最新版本。
所以可以总结,go module的使用分为以下几步:
go mod init $moduleName 初始化module信息。
go build或者go test等标准命令自动更新工程的依赖包信息。
如果有需要可以使用go get $packageName@$version,例如go get foo@v1.2.3, go get foo@master, go get foo@e3702bed2,也可以直接修改go.mod或者使用go mod edit(文章后面会讲到)获取特定的依赖包版本。
以上就是基本的go module工作流程,已经可以满足日常的工作流程要求,下面会详细的讲解go module的其他用法。
详细用法
那么go module一共有多少种玩法呢?直接运行go mod就会有答案:
$ go mod
Go mod provides access to operations on modules.
Note that support for modules is built into all the go commands,
not just 'go mod'. For example, day-to-day adding, removing, upgrading,
and downgrading of dependencies should be done using 'go get'.
See 'go help modules' for an overview of module functionality.
Usage:
go mod <command> [arguments]
The commands are:
download download modules to local cache
edit edit go.mod from tools or scripts
graph print module requirement graph
init initialize new module in current directory
tidy add missing and remove unused modules
vendor make vendored copy of dependencies
verify verify dependencies have expected content
why explain why packages or modules are needed
Use "go help mod
其中init前面我已经讲过了,这里就不再重复。
download
下载依赖包到缓存目录。
edit
提供命令版本编辑go.mod的功能,例如go mod edit -fmt go.mod 会格式化go.mod。
用法 go mod edit [flag] [go.mod]
其中flag选项有:
-fmt 格式化go.mod文件
-require=$package:@version添加依赖,会覆盖已存在的相同依赖。添加依赖更推荐使用go get,因为go get会更新相关的go.mod文件,而edit只会更新你指定的go.mod文件。
-droprequire=$package:@version 移除依赖
-replace=$oldPackage=$newPackage 更新已经存在的依赖。通常用于私有仓库代码覆盖共有仓库。
这里我重点说下-replace 选项,因为在生产中经常遇到的一种情况是由于这样那样的原因我们需要fork一个私有仓库去改动第三方开源库,例如有个小哥针对logrus做了二次开发github.com/gogap/logrus,这个时候就需要用github.com/gogap/logrus替换之前的第三方开源库github.com/sirupsen/logrus,操作如下:
$ go mod edit -replace="github.com/sirupsen/logrus=github.com/gogap/logrus@v0.8.2"
$ go build
go: finding github.com/gogap/logrus v0.8.2
go: downloading github.com/gogap/logrus v0.8.2
go: extracting github.com/gogap/logrus v0.8.2
$ cat go.mod
module mytest
go 1.12
require github.com/sirupsen/logrus v1.4.2
replace github.com/sirupsen/logrus => github.com/gogap/logrus v0.8.2
graph
显示依赖关系(图)。
$ go mod graph
mytest github.com/sirupsen/logrus@v1.4.2
github.com/sirupsen/logrus@v1.4.2 github.com/davecgh/go-spew@v1.1.1
github.com/sirupsen/logrus@v1.4.2 github.com/konsorten/go-windows-terminal-sequences@v1.0.1
github.com/sirupsen/logrus@v1.4.2 github.com/pmezard/go-difflib@v1.0.0
github.com/sirupsen/logrus@v1.4.2 github.com/stretchr/objx@v0.1.1
github.com/sirupsen/logrus@v1.4.2 github.com/stretchr/testify@v1.2.2
github.com/sirupsen/logrus@v1.4.2 golang.org/x/sys@v0.0.0-20190422165155-953cdadca894
tidy
增加缺失的包并且移除没有依赖的包。自动去下载依赖包,并且缓存到$GOPATH/pkg/mod目录下。
需要注意的是,tidy会自动更新依赖包的版本,所以如果不是初建的项目还是尽量少用tidy,尽量用go get精准控制新增的依赖包。
vendor
把依赖包拷贝到vendor目录底下。前面说了那么多想必你一定有一个疑问:go build的时候需要现场去拉取依赖包,如果我的编译机没有外网(访问不了github)怎么办?vendor就是为了应用这种情况,在本地开发机(有外网)执行 go mod vendor 将依赖包拷贝到vendor底下,然后将代码push到编译机 执行 go build -mod=vendor。示例:
$ go mod vendor
$ ls
go.mod go.sum main.go mytest vendor
$ go build -mod=vendor
verify
校验依赖关系
$ go mod verify
all modules verified
why
指出为什么需要依赖包。与graph的区别是,why只能解释某一个特定的依赖包,而graph则是给出完整的依赖关系图。
$ go mod why github.com/konsorten/go-windows-terminal-sequences
github.com/konsorten/go-windows-terminal-sequences
mytest
github.com/sirupsen/logrus
github.com/konsorten/go-windows-terminal-sequences
同工程下的依赖管理
例如建立一个webserver的工程,目录为/Users/saas/src/awesomeProject/webserver,GOPATH设置为/Users/saas, webserver下的目录结构为:
$ tree
.
├── go.mod
├── google
│ └── google.go
├── helloworld
├── server.go
└── userip
└── userip.go
2 directories, 5 files
其中google目录为packge google,userip目录为package userip,那么我们要在server.go如何引用google和userip这两个包呢?只需:
import (
"helloworld/google"
"helloworld/userip"
)
helloworld 是go mod init helloworld时指定的module名称,所以helloworld索引到了webserver目录,helloworld/google指的是webserver底下的google包。如果不指定module的名称,默认是GOPATH下的路径,即为awesomeProject/webserver,引用google包时就需要指定awesomeProject/webserver/google。如果GOPATH没有指定,又没有指定module的名字则报错:
$ export GOPATH=""
$ go mod init
go: cannot determine module path for source directory /Users/saas/src/awesomeProject/webserver (outside GOPATH, no import comments)
指定module就可以了,即便没有GOPATH:
$ go mod init helloworld
go: creating new go.mod: module helloworld
go build时默认会用module的名字(base name)给程序名称,这里是helloworld。如果module名称为 awesomeProject/webserver则是webserver。
Goland IDE打开Go Module
上面例子中发现在Goland IDE中helloworld/google会被标红,说找不到helloworld这个目录,说明IDE的Go Module功能还没有打开,需要如下设置:
settings/Go Modules/ Enable Go Modules 前面的框框打勾