其实我是很喜欢golang这门语言的,易开发,易维护,社区庞大且相对成熟,不过可惜它是谷歌的.
其实谷歌也没什么,主要是谷歌的东西容易用着用着就不能用了.
最早之前用golang的时候,就发现go get这个命令安装东西时如果有golang官方的依赖就会发现被墙了,用起来非常的麻烦.不过当时服务器部署在海外,一切都还好.
今天就记录一下在国内使用包时免FQ的办法 gopm(gopem项目已经下了,推荐使用go mod)
go mod
和go proxy
来做依赖管理go 1.13>=版本推荐使用
#依赖管理三个阶段GOPATH,GOVENDOR,go mod
~/go/src/
下了~/go/pkg/mod/
下存储go mod常用命令和设置#
go mod download 下载依赖
go mod tidy 同步依赖包,添加需要的,移除多余的
go mod vendor 将依赖包放入项目下的vendor目录
go get 下载/升级依赖,go mod不再下载源码进$GOPATH/src
,而是在$GOPATH/pkg/mod
注意:
go mod模式不推荐使用vendor目录,而是直接从cache使用下载的包.
go mod模式默认忽略vendor目录,可以通过flag-mod=vendor
设置为GOFLAGS=-mod=vendor
来设置为vendor模式.但是该模式下无法正常使用go get
goproxy
来下载依赖使用go 1.13以下版本推荐使用
#export GOPROXY=https://goproxy.cn
go get
命令而不会被墙了,下载的内容还是存储在GOPATH中这个包有一个golang.org
的依赖如果直接go get
是无法下载的.
go get -u -v github.com/aliyun/aliyun-oss-go-sdk/oss
完成
设置GOPROXY
地址,开启go mod
#
export GO111MODULE=on
export GOPROXY=https://goproxy.cn
go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct
# 或者使用下面这个, https://goproxy.cn是七牛云的项目
go env -w GOPROXY=https://goproxy.io,direct
GOPROXY=https://goproxy.cn,direct 配置`GOPROXY`的地址`direct`代表当`go`在抓取目标模块时直接去目标模块的源头(比如 GitHub) 去抓取
GO111MODULE=on 开启`go mod`依赖管理功能
如果有不想走proxy
的可以这样设置
# 设置不走 proxy 的私有仓库,多个用逗号相隔
go env -w GOPRIVATE=*.corp.example.com
# 例如:来自码云,gitlab,阿里云的的代码不走proxy
go env -w GOPRIVATE=*.gitee.com,code.aliyun.com
此时已可以获取包了
# 这时候使用go get 去获取之前下不到的包,会发现非常的快.
go get -u -v go.uber.org/zap
go.mod
文件go.mod文件内容
module awesome-project 项目名称
go 1.13 语言的版本
awesome-project
项目目录下go get下载所需要的包此时我们就可以为不同的项目下载不同的包了
# 这时候使用go get 去获取之前下不到的包,会发现非常的快.
go get -u -v go.uber.org/zap
# 如果要下载指定版本的包只需要在后面@版本号即可
go get -u -v go.uber.org/zap@v1.11
# 如果要升级,不指定版本号即可
go get -u -v go.uber.org/zap
# 清洁依赖,删除`go.mod`中没有被使用的包的条目(不会删除包文件)
go mod tidy
go.mod
文件已有改变,并且多了一个go.sum
文件go.mod文件内容
module awesome-project 项目名
go 1.13 语言版本
require (
go.uber.org/atomic v1.5.1 // indirect 代表没有被用到
go.uber.org/multierr v1.4.0 // indirect
go.uber.org/zap v1.13.0 // indirect
golang.org/x/lint v0.0.0-20200130185559-910be7a94367 // indirect
golang.org/x/tools v0.0.0-20200206050830-dd0d5d485177 // indirect
)
go.sum文件的部分内容,里面有各个包的hash和版本号
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
......
import
没有下载的包首次直接编译会失败(goland没事).但同时也会将包下载下来, 再次编译的时候就没问题了
.
package main
import "github.com/astaxie/beego"
func main() {
beego.Run()
}
go.mod
发现多了一条beego的记录,可见go会帮我们自动下载需要的依赖
module awesome-project
go 1.13
require (
github.com/astaxie/beego v1.12.0 // indirect
github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644 // indirect
)
之前没有用go mod现在想用怎么办?
使用go mod命令来创建go.mod然后再编译
go mod init module名称(会自动命名为项目名称, 一般和项目名保持一致即可)
go build ./...
build过程中每次遇到import
都会触发go modules通过镜像帮我们拉去所需要的包
# 将当前目录下所有的go文件全部编译
go build ./...
# 编译案例,可以看到build后都已经在下载所需要的包了
go build ./...
go: finding github.com/go-sql-driver/mysql v1.5.0
go: finding github.com/go-xorm/xorm v0.7.9
go: downloading github.com/go-sql-driver/mysql v1.5.0
go: downloading github.com/go-xorm/xorm v0.7.9
go: finding gopkg.in/fatih/set.v0 v0.2.1
go: finding github.com/gorilla/websocket v1.4.1
go: finding github.com/pkg/errors v0.9.1
go: downloading github.com/gorilla/websocket v1.4.1
go: downloading github.com/pkg/errors v0.9.1
go: downloading gopkg.in/fatih/set.v0 v0.2.1
go: extracting github.com/go-sql-driver/mysql v1.5.0
go: extracting github.com/gorilla/websocket v1.4.1
go: extracting github.com/pkg/errors v0.9.1
go: extracting github.com/go-xorm/xorm v0.7.9
go: extracting gopkg.in/fatih/set.v0 v0.2.1
完成
这是一个很短暂的项目,官方在推出vendor支持以后很快就推出了go mod
,不建议再用,费劲.
即在项目目录下新建一个vendor目录, 将所有依赖的第三方包全部放在vendor下.
go语言会优先在此目录寻找依赖.
可以看到vendor下面还有vendor,不管有我们的vendor,还有我们引用第三方时,他们自己的vendor
├── vendor
│ ├── config
│ └── github.com
│ ├── aliyun
│ │ └── aliyun-oss-go-sdk
│ │ ├── oss
│ │ └── sample
│ ├── go-sql-driver
│ │ └── mysql
│ ├── julienschmidt
│ │ └── httprouter
│ └── tencentyun
│ └── cos-go-sdk-v5
│ ├── costesting
│ ├── debug
│ ├── example
│ │ ├── batch
│ │ ├── bucket
│ │ ├── object
│ │ ├── service
│ │ └── sts
│ └── vendor
│ └── github.com
│ ├── google
│ │ └── go-querystring
│ │ └── query
│ ├── mozillazg
│ │ └── go-httpheader
│ └── stretchr
│ └── testify
│ ├── _codegen
│ ├── assert
│ ├── http
│ ├── mock
│ ├── require
│ ├── suite
│ └── vendor
│ └── github.com
│ ├── davecgh
│ │ └── go-spew
│ │ └── spew
│ ├── pmezard
│ │ └── go-difflib
│ │ └── difflib
│ └── stretchr
│ └── objx
没网的时候可以这么干,但是要注意依赖的依赖,这个问题.
go get -v -u github.com/gpmgo/gopm
# 查看当前工程依赖
gopm list
# 显示依赖详细信息
gopm list -v
# 列出文件依赖
gopm list -t [file]
# 拉取依赖到缓存目录
gopm get -r xxx
# 仅下载当前指定的包
gopm get -d xxx
# 拉取依赖到$GOPATH
gopm get -g xxx
# 检查更新所有包
gopm get -u xxx
# 拉取到当前所在目录
gopm get -l xxx
# 运行当前目录程序
gopm run
# 生成当前工程的 gopmfile 文件用于包管理
gopm gen -v
# 根据当前项目 gopmfile 链接依赖并执行 go install
gopm install -v
# 更新当前依赖
gopm update -v
# 清理临时文件
gopm clean
# 编译到当前目录
gopm bin
安装gopm
go get -v -u github.com/gpmgo/gopm
这是我们回到~/go 中的我们自己的GOPATH的目录 ls一下
可以看到$GOPATH下的src下多了一个github.com 的目录,和我们的目录放在一起
```shell
~/go ⌚ 2:06:05
$ tree -L 2
.
├── bin
│ └── gopm
└── src
├── github.com
└── learnGo
这时候我们到~/go/bin/gopm 运行该文件
~/go/bin/gopm get -g -v -u golang.org/x/tools/cmd/goimports
这是安装成功之后, $GOPATH 下的src中会多一个golang.org的目录和我们的目录放在一起
~/go ⌚ 2:19:31
$ tree -L 2
.
├── bin
│ └── gopm
└── src
├── github.com
├── golang.org
└── learnGo
很显然我们在编码时的目录也是在src中运行的, bin是可执行文件
在~/go/bin 目录下执行 go install 安装goimports 安装之后会在~/go/bin目录下生成一个可执行的文件
~/go/bin ⌚ 2:26:38
$ go install ../src/golang.org/x/tools/cmd/goimports