Golang Module的使用

前言: 在Golang1.11之前的版本中,官方没有提供依赖和包管理工具。开发者通常会使用vendor或者glide的方式来管理依赖(也有直接使用GOPATH多环境方式),而在Golang1.11之后官方终于出了名为go modules的版本管理机制。

注意:

  • 在Golang1.11版本中需要使用export GO111MODULE=on来显式开启go module
  • 在Golang1.12之后默认开启了module

Golang Module快速入门

初始化项目

# 在GOPATH之外创建一个项目目录
➜  mkdir cmdb-job

# 进入目录后初始化一个module
➜  cd cmdb-job
➜  go mod init cmdb-job
go: creating new go.mod: module cmdb-job

# 查看生成的mod.md
➜  cat go.mod
module cmdb-job

go 1.12

# 使用第三方模块编写一丢丢代码逻辑
# 一个字符串简单几种加密方式的简单工具
➜ cat main.go
/*================================================================
*Copyright (C) 2019 BGBiao Ltd. All rights reserved.
*
*FileName:main.go
*Author:BGBiao
*Date:2019年09月07日
*Description:
*
================================================================*/
package main
import (
    "fmt"
    "github.com/xxbandy/go-utils/crypto"
)

func main() {
    fmt.Println(crypto.Md5("hello"))
    fmt.Println(crypto.Hmac("key2", "hello"))
    fmt.Println(crypto.Sha1("hello"))
    fmt.Println(crypto.HmacSha1("key2", "hello"))
}

# 查看下项目结构和依赖
➜ tree -L 1 .
.
├── go.mod
├── go.sum
└── main.go

测试运行项目

# 测试运行
# 第一次运行会自动检查代码里的第三方依赖包,并下载和接下项目依赖的包
➜  go run main.go
go: finding github.com/xxbandy/go-utils/crypto latest
go: finding github.com/xxbandy/go-utils latest
go: downloading github.com/xxbandy/go-utils v0.0.0-20190506113112-d88d469a26b2
go: extracting github.com/xxbandy/go-utils v0.0.0-20190506113112-d88d469a26b2
5d41402abc4b2a76b9719d911017c592
f1b90b4efd0e5c7db52dfa0efd6521a3
aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d
79806c50bab4825a371e3c4fff80bae0c731d54e

# 第二次运行
➜  go run main.go
5d41402abc4b2a76b9719d911017c592
f1b90b4efd0e5c7db52dfa0efd6521a3
aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d
79806c50bab4825a371e3c4fff80bae0c731d54e

# 查看管理mod的依赖配置
## go.mod会记录项目所需依赖以及具体的版本号记录(go-utils这个库没有版本,所以会根据提交日期和commitid来唯一标识版本)
➜  cat go.mod
module cmdb-job

go 1.12

require github.com/xxbandy/go-utils v0.0.0-20190506113112-d88d469a26b2 // indirect

## go.sum文件会记录依赖树的详细信息
➜  cat go.sum
github.com/xxbandy/go-utils v0.0.0-20190506113112-d88d469a26b2 h1:SD6OuR8EUvCmiBDoxItcFYXIMuse45HvuSh3ho0AAeU=
github.com/xxbandy/go-utils v0.0.0-20190506113112-d88d469a26b2/go.mod h1:XhyyBI KH4XEIbw3EhMFjZfJcV3kDK4iSAT7zZYd Uc=

Go Module的其他功能

注意:go mod 还有一些其他比较有意思的工具,比如可以打印依赖树,比如可以查看哪些模块在哪些包引用了

go mod的其他特性

# 执行go help mod可以查看到以下子命令
➜ go help mod
    download    download modules to local cache       # 下载模块包到本地缓存
    edit        edit go.mod from tools or scripts     # 从工具或脚本中修改go.md内容(暂时没觉得很好用)
    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         # 将依赖拷贝到vendor中(会将依赖打包到当前目录下的vendor目录)
    verify      verify dependencies have expected content  # 检查依赖内容
    why         explain why packages or modules are needed # 解释为什么哪些包或者模块被需要


# 查看当前项目的依赖树(项目复杂时比较有用)
➜  go mod graph
cmdb-job github.com/xxbandy/[email protected]
# 查看模块或包在哪里被依赖了
➜  go mod why github.com/xxbandy/go-utils/crypto
# github.com/xxbandy/go-utils/crypto
cmdb-job
github.com/xxbandy/go-utils/crypto

# 拷贝一份依赖到项目本地
# 会将项目的依赖包拷贝到项目的vendor目录中
➜  go mod vendor
➜  tree -L 3 .
.
├── go.mod
├── go.sum
├── main.go
└── vendor
    ├── github.com
    │   └── xxbandy
    └── modules.txt

注意:这个时候可能会有人有疑问了,既然go mod vendor将依赖拷贝一份到项目家目录的vendor目录了,那原始的依赖存在哪里?比如我们之前没有依赖管理之前,默认的依赖都是在$GOPATH/src/下面的

其实,在使用了go mod之后,项目依赖的全部依赖包都会在$GOPATH/pkg/mod/cache/download/中统一缓存下来,而项目中的go.md中会记录真正的版本信息,去缓存中引用即可。

# 查看go mod之后缓存的依赖包
➜  tree -L 3   ${GOPATH}/pkg/mod/cache/download/
${GOPATH}/pkg/mod/cache/download/
└── github.com
    └── xxbandy
        └── go-utils

一个开源项目示例

我们就以golang-gin-vue项目为例来看下go mod的一些功能吧.

golang-gin-vue是一个使用gin框架编写后端接口,结合vue来渲染前端的一个示例项目.

# 克隆项目到本地
➜ git clone https://github.com/xxbandy/golang-gin-vue.git

➜  cd golang-gin-vue

# 使用go mod初始化项目
➜  golang-gin-vue git:(master) go mod init golang-gin-vue
go: creating new go.mod: module golang-gin-vue

# 初始化后会默认生成go.mod文件,但是不会加载依赖包,需要go run或者go build来自动加载依赖
➜  golang-gin-vue git:(master) ✗ go build main.go
go: finding github.com/gorilla/mux v1.7.3
go: downloading github.com/gorilla/mux v1.7.3
go: extracting github.com/gorilla/mux v1.7.3

# 查看go.mod文件
➜  golang-gin-vue git:(master) ✗ cat go.mod
module golang-gin-vue
go 1.12
require (
    github.com/gin-gonic/gin v1.4.0 // indirect
    github.com/gorilla/mux v1.7.3 // indirect
)

# 打印依赖树关系
## 基本上可以知道项目和库依赖了哪些库
➜  go mod graph
golang-gin-vue github.com/gin-gonic/[email protected]
golang-gin-vue github.com/gorilla/[email protected]
github.com/gin-gonic/[email protected] github.com/gin-contrib/[email protected]
github.com/gin-gonic/[email protected] github.com/golang/[email protected]
github.com/gin-gonic/[email protected] github.com/json-iterator/[email protected]
github.com/gin-gonic/[email protected] github.com/mattn/[email protected]
github.com/gin-gonic/[email protected] github.com/modern-go/[email protected]
github.com/gin-gonic/[email protected] github.com/modern-go/[email protected]
github.com/gin-gonic/[email protected] github.com/stretchr/[email protected]
github.com/gin-gonic/[email protected] github.com/ugorji/[email protected]
github.com/gin-gonic/[email protected] golang.org/x/[email protected]
github.com/gin-gonic/[email protected] gopkg.in/go-playground/[email protected]
github.com/gin-gonic/[email protected] gopkg.in/go-playground/[email protected]
github.com/gin-gonic/[email protected] gopkg.in/[email protected]
github.com/stretchr/[email protected] github.com/davecgh/[email protected]
github.com/stretchr/[email protected] github.com/pmezard/[email protected]
github.com/stretchr/[email protected] github.com/stretchr/[email protected]
github.com/mattn/[email protected] golang.org/x/[email protected]
gopkg.in/[email protected] gopkg.in/[email protected]
golang.org/x/[email protected] golang.org/x/[email protected]
golang.org/x/[email protected] golang.org/x/[email protected]
golang.org/x/[email protected] golang.org/x/[email protected]

# 查看gin这个模块被哪里需要(golang-gin-vue项目和gin框架本身需要)
➜ go mod why github.com/gin-gonic/gin
# github.com/gin-gonic/gin
golang-gin-vue
github.com/gin-gonic/gin

Tips

我们在使用Golang进行开发过程中,通常会发现各种第三方库会依赖golang.org/x之类的原生库,或者一些其他国外大厂提供的共有库,由于政策原因,我们是无法直接访问国外网站来下载依赖库的(网速也有限制),因此在开发过程中也是比较头疼的. 这个时候通常大家都会去采用科学上网,或者通过一些代理的方式来解决. 而在Golang高版本中,包含了goproxy特性,用户可以直接指定代理来下载依赖的第三方库,一方面解决了下载速度的问题,另外一方面也解决了无法访问的第三方库的下载。

注意:goproxy必须在go1.11以上版本,并且开启了go module机制后才能使用的(因为我当前的环境都是1.12,大家可以验证下小版本是否支持)

而在国内,质量比较好的几个goproxy代理大概有如下几个:

  • https://goproxy.cn : 七牛云赞助支持的开源代理
  • https://mirrors.aliyun.com/goproxy/ : 阿里云官方维护的go代理
  • https://goproxy.io/ : 也是一个开源的go代理

go代理使用

# 开启go module支持
# golang1.11 需要手动开启,golang1.12之后默认会开启
$ export GO111MODULE=on

# 设置代理(上述三个代理地址都可以)
$ export GOPROXY=https://goproxy.cn

# 下载第三方库

$ go get -v golang.org/x/net/websocket
Fetching https://goproxy.cn/golang.org/x/net/websocket/@v/list
Fetching https://goproxy.cn/golang.org/x/net/@v/list
go: finding golang.org/x/net latest
Fetching https://goproxy.cn/golang.org/x/net/@latest
Fetching https://goproxy.cn/golang.org/x/net/@v/v0.0.0-20190827160401-ba9fcec4b297.mod
golang.org/x/net/websocket

自从使用了goproxy之后,妈妈再也不用担心无法下载第三方库拉,爽到不行.欢迎关注我的公众号Golang Module的使用_第1张图片

你可能感兴趣的:(Golang Module的使用)