Go mod 开发中常用玩法 — 开发必备
go modules
是 golang 1.11 新加的特性。
那么问题来了,它解决了什么问题,其实核心的问题就是,他可以没有GoPath这个概念,所以很方便,但是当你不会使用的时候,你会觉得它很不好用。
PS:go.mod文件一旦创建后,它的内容将会被go toolchain全面掌控。go toolchain会在各类命令执行时,比如go get、go build、go mod等修改和维护go.mod文件。
简单使用
比如,现在有一个需求是,我们要创建一个新项目,项目名字为 go-kit-demo,此时我们需要go-kit的依赖,那么怎么办呢
第一步
% mkdir go-kit-demo % cd go-kit-demo % go mod init go-kit-demo // 初始化一个项目名为 go-kit-demo,这个路径其实是你相对于GOPATH的路径,以后你的包就是 import "go-kit-demo/util" 之类的 % ls go.mod // 发现多了个文件 % cat go.mod module go-kit-demo // 模块名字 go 1.13 // go版本 % go mod edit -require=github.com/go-kit/kit@latest //添加go-kit的依赖 % go mod download //下载依赖 % cat go.mod module go-kit-demo go 1.13 require github.com/go-kit/kit v0.10.0 // indirect % ls go.mod go.sum//校验包 复制代码
第二步,其实就是需要代码,让编辑器可以找到,显然目前go官方不支持的,需要第三方。
但是这里你无法直接使用go-kit,理由是,goland工具不支持,这种模块依赖,所以必须引入到vendor中,也就是。
这里推荐一个工具,他可以将依赖打包到vendor进去,相当nice
https://github.com/nomad-software/vend 复制代码
根据要求来就行了
go get github.com/nomad-software/vend 复制代码
就像下面这样子
~/go/code/mode-test % vend vend: copying cloud.google.com/go (v0.34.0) vend: copying github.com/BurntSushi/toml (v0.3.1) vend: copying github.com/Knetic/govaluate (v3.0.1-0.20171022003610-9aa49832a739+incompatible) vend: copying github.com/Shopify/sarama (v1.19.0) vend: copying github.com/Shopify/toxiproxy (v2.1.4+incompatible) vend: copying github.com/VividCortex/gohistogram (v1.0.0) vend: copying github.com/afex/hystrix-go (v0.0.0-20180502004556-fa1af6a1f4f5) vend: copying github.com/alecthomas/template (v0.0.0-20190718012654-fb15b899a751) vend: copying github.com/alecthomas/units (v0.0.0-20190717042225-c3de453c63f4) vend: copying github.com/apache/thrift (v0.13.0) vend: copying github.com/armon/circbuf (v0.0.0-20150827004946-bbbad097214e) 复制代码
所以还是很方便的,可以将依赖全部copy到vendor下,就可以愉快的使用了。
其他命令
比如说国内源的问题,需要修改一下
export GOPROXY=https://goproxy.cn 复制代码
其次就是,比如低版本的go ,可能需要强制开启go mod
export GO111MODULE=on 复制代码
像其他命令我就不介绍了,比如还有常用的可能就是 go mod vendor
,将依赖copy到vendor目录下,但是有个问题就是,它只会copy代码依赖的东西,所以我们有些时候是不方便的,因此,需要使用到我上面推荐的工具。
比如说
go get github.com/go-kit/kit //此时会在go.mod文件中添加依赖,也就是说不需要手动的去执行 go mod edit -require=github.com/go-kit/kit@latest了 复制代码
还有其他命令
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 [arguments] The commands are: download download modules to local cache//下载 edit edit go.mod from tools or scripts//编辑go.mod 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 // copy到vendor verify verify dependencies have expected content // 校验 why explain why packages or modules are needed Use "go help mod " for more information about a command. 复制代码
go.mod 提供了 module
, require
、 replace
和 exclude
四个命令
module require replace exclude
其实这些不需要care
本地仓库如何解决
需求,我们现在有另外一个项目,我们这个项目需要引入。
PS: 进入公司,一般你会将公司的代码,放在同一个目录下面,也就是上一级目录是一样的,所以我们也遵守这个规范,理由其实很简单,因为方便环境。
初始化 A\B项目,名字为 demo-1,demo-2
~/go/code/test % cd demo-1 ~/go/code/test/demo-1 % ls ~/go/code/test/demo-1 % go mod init demo-1 go: creating new go.mod: module demo-1 复制代码
我们目前目录结构是这样的:
~/go/code/test % tree . . ├── demo-1 │ └── go.mod └── demo-2 ├── api │ └── userservice.go └── go.mod 3 directories, 3 files 复制代码
我们现在demo-1这个项目,需要使用 user-service这个接口
package api type UserService interface{ GetUserInfo()*UserInfo } type UserInfo struct{ Name string `json:"name"` Age int `json:"age"` } 复制代码
此时只需要在 demo-1里面做一下替换就可以了,如下图所示
module demo-1 go 1.13 require demo_2 v0.0.0 replace demo_2 => ../demo-2 复制代码
然后我们demo-1就可以愉快的使用了
package main import ( "demo_2/api" "fmt" ) func main() { info := api.UserInfo{ Name: "tom", Age: 18, } fmt.Println(info) } 复制代码
那么现实中,可能依赖包要更新,需要及时的拉去master,这个更新怎么办,很简单,只需要执行 go mod vendor
从新拉去一下
注意的一点是 本地包,无法校验hash
为什么要必须使用vendor目录
- 1、依赖可能是本地,可能是私有仓库,无法解决
- 2、生产环境可能拉去慢
- 3、没有通用的解决方案,等go以后发展吧
其中 go build -mod=vendor
的意思是强制开启vendor模式,依赖只会去vendor目录找,其他都不会care,也不会网络环境找。
私人仓库如何解决
全部公有仓库,没啥事,但是私有怎么半
这三个方案,理论上都可行,但是都有缺陷。
goproxy代理,本身并不解决从gitlab服务器获取私有项目代码的问题,也没有成熟的鉴权机制。因此比较适合静态公共代码。
例子可以看: goproxy.cn/
nginx代理,同样不解决认证的问题,我配置了一个代理,ssl认证失败(弱鸡本鸡),理论上这个方案是最好的解决方案。
go replace,需要在每个项目中都添加,更新依赖也比较复杂。
所以采用的方案是,还是本地依赖。
目前网上的解决方案都是修改本地的git,配置,通过配置一些信息之类的,自行百度,但是还是又问题。最好还是搭建代理比较好,从代理层解决,可以参考上面的go proxy。
欢迎关注我们的微信公众号,每天学习Go知识