go之前对第三方包的管理不上心,其他语言比如python有pip,nodejs有npm,而go却没有一个官方的管理工具。
在go 1.11之前,开发者需要要关注GOPATH环境变量,这对于开发者来说不友好。
经过几次变更后,go于1.12版本开始正式使用go Module,go终于有了一个官方的处理方式,开发者也可以抛弃GOPATH了。
本次使用的go版本为1.15.6,建议使用1.13或以上的版本,旧的方式就不要再关注了,让它随风而去吧。
go version go1.15.6 darwin/amd64
本次使用的系统为Ubuntu,实验路径/opt/golang
root@xxg:/opt/golang# pwd /opt/golang
假设我们有个项目叫caseshow,我们先创建这个目录,并初始化一下
mkdir caseshow cd caseshow go mod init caseshow
此时在caseshow目录下会自动产生一个go.mod文件,内容如下:
module caseshow go 1.15
比如我们想使用一个redis客户端:github.com/go-redis/redis/v8,在当前路径下直接执行go get命令即可:
go get github.com/go-redis/redis/v8
最近访问github很慢,可以先设置一下代理
go env -w GO111MODULE=on go env -w GOPROXY=https://goproxy.io,direct
设置好之后,下载第三方库
root@xxg:/opt/golang/caseshow# go get github.com/go-redis/redis/v8 go: downloading github.com/go-redis/redis v6.15.9+incompatible go: downloading github.com/go-redis/redis/v8 v8.4.2 go: github.com/go-redis/redis/v8 upgrade => v8.4.2 go: downloading go.opentelemetry.io/otel v0.14.0 go: downloading github.com/cespare/xxhash/v2 v2.1.1 go: downloading github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f
目录下会多一个go.sum文件,go.mod文件里面也多了关于redis库的内容
root@xxg:/opt/golang/caseshow# ls go.mod go.sum root@xxg:/opt/golang/caseshow# cat go.mod module caseshow go 1.15 require github.com/go-redis/redis/v8 v8.4.2 // indirect
之后就可以直接用了,写个redis.go测试下:
package main import ( "context" "fmt" "github.com/go-redis/redis/v8" ) var ctx = context.Background() func ExampleClient() { rdb := redis.NewClient(&redis.Options{ Addr: "localhost:6379", Password: "", // no password set DB: 0, // use default DB }) err := rdb.Set(ctx, "key", "value", 0).Err() if err != nil { panic(err) } val, err := rdb.Get(ctx, "key").Result() if err != nil { panic(err) } fmt.Println("key", val) val2, err := rdb.Get(ctx, "key2").Result() if err == redis.Nil { fmt.Println("key2 does not exist") } else if err != nil { panic(err) } else { fmt.Println("key2", val2) } // Output: key value // key2 does not exist } func main() { ExampleClient() }
测试正常:
root@xxg:/opt/golang/caseshow# go run redis.go key value key2 does not exist
整个过程没有GOPATH什么事。
在项目开发中会复用本地的一些代码,这就涉及到了本地包的引入。
无需import,直接使用对应的方法。go build
时,在后面加上要用的文件名即可,比如
go build main.go main_command.go
go run
调试时,在后面加上要用的文件名即可,比如
go run main.go main_command.go
在同路径下不能存在多个package名,如果要定义其他的package,可以创建一个对应名字的目录,把代码放下面,之后再引用。
假设在caseshow中有个本地开发的包mymodule,里面有个方法Pprint,结构如下
# tree . ├── go.mod ├── go.sum ├── mymodule │ └── pprint.go └── redis.go 1 directory, 4 files
pprint.go的代码如下:
package mymodule import "fmt" func Pprint(a string){ fmt.Println("pprint ", a) }
如果caseshow目录下的其他地方要用这个方法,则使用caseshow + package名称导入即可。
比如main.go:
package main import "caseshow/mymodule" func main(){ mymodule.Pprint("jack") }
直接运行:
# go run main.go pprint jack
假设有另一个项目caselive,与caseshow同级,该目录下有个包yourmodule,里面有个方法Yprint:
# tree . ├── caselive │ ├── go.mod │ ├── main.go │ └── yourmodule │ └── yprint.go └── caseshow ├── go.mod ├── go.sum ├── main.go ├── mymodule │ └── pprint.go └── redis.go 4 directories, 8 files
yprint.go的内容如下:
package yourmodule import "fmt" func Yprint(a string){ fmt.Println("yprint ", a) }
此时在caseshow中要调用caselive中yourmodule的Yprint方法,可以用replace
参数来实现。
在caseshow的go.mod中增加caselive的引入:
require mypackage v0.0.0 replace mypackage => ../mypackage
完整内容如下:
module caseshow go 1.15 require github.com/go-redis/redis/v8 v8.4.2 // indirect require caselive v0.0.0 replace caselive => ../caselive
之后就能直接调用了:
package main import "caseshow/mymodule" import "caselive/yourmodule" func main(){ mymodule.Pprint("jack") yourmodule.Yprint("jack") }
运行测试下:
# go run main.go pprint jack yprint jack