本文由 简悦 SimpRead 转码, 原文地址 blog.csdn.net
前言≈
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 什么事。
本地包
在项目开发中会复用本地的一些代码,这就涉及到了本地包的引入。
情况1. 同路径引用其他文件
无需 import,直接使用对应的方法。go build
时,在后面加上要用的文件名即可,比如
go build main.go main_command.go
go run
调试时,在后面加上要用的文件名即可,比如
go run main.go main_command.go
情况2. 同目录下
在同路径下不能存在多个 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
情况3. 不同目录下
假设有另一个项目 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