go mod的基础使用-科普

文章主要是针对新人来介绍go mod是啥以及新手如何使用,老手不用看。现阶段go mod已经完全GA了,你会用了的话会非常方便

像python的项目根目录有 requirement.txt
记录依赖包,nodejs是 packages.json
,同样go的包管理从早期的go dep(gopkg)到vendor到现在的go mod.

go dep很早,没有接触过,如果你接触的项目有go dep,看完本文希望你可以学会改造你手上的老项目,vendor则是把包都存放项目的根路径的 vendor
文件夹里,就像下面。这会导致一个项目很大,多大40M以上。

$ tree -d -L 1
.
├── cert
├── cmd
├── docs
├── install
├── ipvs
├── net
├── pkg
├── test
├── vendor
└── version

go是一个开放的态度下诞生的语言,并没有其他语言那样官方维护一个中心库,go的库大多数都是直接github上的。

开发者把包存放到github上,一般打tag作为版本,master作为pr和修补,定期cut出新tag。这个做法和实际的开发流程一样。在这个环境下,go的包管理不可能单单存放一个版本号,所以 go.mod
是存放版本号, go.sum
记录git的hash值,以防止篡改。

这样并没有依赖包存在项目文件夹里导致项目代码体积过大,用户通过 go mod download
命令会调用git去拉取依赖,或者直接 go run
或者 go build
也会下载。

go mod如何使用

基础配置和相关环境变量

新手的话推荐使用1.13+版本的go,go mod是诞生于1.11版本,在1.13差不多定型了。1.12之前使用gomod的话需要配置环境变量 GO111MODULE=on
,这样才会开启go mod,而1.13以后默认变量为 auto
,会根据项目下的文件夹和文军自动识别是否是go mod。例如下面就是一个纯go mod项目

api/
docker/
models/
router/
service/
docs/
Dockerfile
go.mod
go.sum
main.go
README.md

如果之前用vendor由于依赖在本地,所以刚上手go mod的时候会发现 go get
拉取超时,实际上我们可以配置环境变量让go拉取包的时候走代理绕过墙,也就是配置 GOPROXY
。这个变量只有go mod启用下才能使用。

同时要注意的一点是,1.13+下 GOPROXY
能配置多个代理地址,下面是常见的地址

export GO111MODULE=on
export GOPROXY=https://goproxy.cn,https://mirrors.aliyun.com/goproxy/,https://goproxy.io,direct

direct是直连,用于内网开发拉取内网的私有库。默认拉取的时候会从前到后retry,也可以 GONOPROXY
配置某个不走代理

同时,也不要像以前以及网上的那些老视频教程那样把项目放在GOPATH上,现在GOPATH的概念越来越淡化了,不懂go mod下如果还是把项目创建在GOPATH下回容易出错。

同时也不要创建啥 src pkg bin
目录了,都是过去式了,可以看上面那个go mod的项目文件列表,压根没有src啥的。

终端编译或者run

配置了两个环境变量,项目也是go mod的话我们直接go run main.go或者build都会自动拉取包,不用担心墙

gomod和vendor共存

现在并不是所有用户都接受gomod,很多开源项目为了兼容新老用户,go mod和vendor都是有的,类似目录

...
vendor/
go.mod
go.sum
main.go

这样的项目我们编译的时候命令为

go build -mod vendor main.go

goland下的使用

分为新建项目和直接打开项目文件作为项目,不要把项目存放在 GOPATH

goland新建gomod开局项目

New Project
的时候选择 Go Modules(vgo)
,我们写 Proxy
就是 GOPROXY
,勾上 Vendoring mode
就是上面go mod和vendor共存的项目,如果你自己写新项目就不要勾选vendor了,vendor应该是过去式了。

goland打开一个项目,或者改造一个项目

如果是打开一个文件夹的项目,或者 New Project
的时候已经选择了 Go Modules(vgo)
上面的 Go
,我们需要配置下面

  • Settings
    –> GO
    –> GOPATH
    –> Project GOPATH下面如果不为空,就选中后点击右边的减号删掉
  • Settings
    –> GO
    –> Go Modules(vgo)
    勾选 Enable Go Modules(vgo) integration
    ,写上Proxy

我们也可以终端操作
1.13 go mod init的话默认会以项目文件夹名为module名,例如下面

F:\go\Installer>go mod init
go: creating new go.mod: module Installer

执行后go.mod第一行为

module Installer

假如我们项目路径为

.
|-- api
|   |-- ks.go
|   `-- machine.go
|-- go.mod
|-- go.sum
|-- main.go

我们要在main.go里引用api包的话就写

import "Installer/api"

第一个就是go.mod里第一行的module名,不仅限于一个单词,有的人会以公司网站或者github地址,例如

module github.com/zhangguanzhang/Installer

这种名字下我们引用api就是

import "github.com/zhangguanzhang/Installer/api"

1.14开始 go mod init
后面必须接module名字

$ go mod init
go: cannot determine module path for source directory F:\go\test (outside GOPATH, module path must be specified)

Example usage:
        'go mod init example.com/m' to initialize a v0 or v1 module
        'go mod init example.com/m/v2' to initialize a v2 module

Run 'go help mod init' for more information.

有时候goland里设置改了不一定生效,所以我们得终端执行 go mod init
触发下,然后关闭goland,删除掉项目下的 .idea
,然后右击项目文件夹用goland打开。在设置里去配置下GOPROXY之类的。