go 1.18 引入了功能泛型 (Generics), 同时还引入的多模块工作区 (Workspaces) 和模糊测试 (Fuzzing)。
Go 多模块工作区能够使开发者能够更容易地同时处理多个模块的工作, 如:
go.work
文件到 git 上, 因为它主要用于本地代码开发;$GOPATH
路径下执行, 生成 go.work
文件go work init
初始化工作区文件, 用于生成 go.work
工作区文件初始化并写入一个新的 go.work
到当前路径下, 可以指定需要添加的代码模块
示例: go work init ./hello
将本地仓库 hello 添加到工作区
hello 仓库必须是 go mod 依赖管理的仓库 (./hello/go.mod
文件必须存在)
命令示例:
go work use ./example 添加一个模块到工作区
go work use ./example ./example1 添加多个模块到工作区
go work use -r ./example 递归 ./example 目录到当前工作区
删除命令使用 go work edit -dropuse=./example 功能
go work edit
用于编辑 go.work
文件可以使用 edit
命令编辑和手动编辑 go.work
文件效果是相同的, 示例:
go work edit -fmt go.work 重新格式化 go.work 文件
go work edit -replace=github.com/link1st/example=./example go.work 替换代码模块
go work edit -dropreplace=github.com/link1st/example 删除替换代码模块
go work edit -use=./example go.work 添加新的模块到工作区
go work edit -dropuse=./example go.work 从工作区中删除模块
go work sync
将工作区的构建列表同步到工作区的模块
go env GOWORK
查看环境变量, 查看当前工作区文件路径 可以排查工作区文件是否设置正确, go.work
路径找不到可以使用 GOWORK
指定
> go env GOWORK
$GOPATH/src/link1st/link1st/workspaces/go.work
go 1.18
use (
./hello
./example
)
replace (
github.com/link1st/example => ./example1
)
# 单模块结构
use ./hello
# 多模块结构
use (
./hello
./example
)
同时指定报错信息:
go: workspace module http://github.com/link1st/example is replaced at all versions in the go.work file. To fix, remove the replacement from the go.work file or specify the version at which to replace the module.
同时在 use 和 replace 指定相同的本地路径
go 1.18
use (
./hello
./example
)
replace (
github.com/link1st/example => ./example
)
go.mod 中定义替换为本地仓库 example
replace (
github.com/link1st/example => ./example1
)
go.work 中定义替换为本地仓库 example1
replace (
github.com/link1st/example => ./example1
)
export GOWORK="~/go/src/test/go.18/workspace/go.work"
export GOWORK=off
演示如何使用多模块工作区功能。在现在微服务盛行的年代, 一个人会维护多个代码仓库, 很多的时候是多个仓库进行同时开发
假设我们现在进行 hello 仓库开发, 实现的功能是, 实现将输入的字符串反转并输出, 字符串反转功能依赖于 http://github.com/link1st/example (下文统称 example) 公共仓库实现
新建 hello 项目
mkdir hello
cd hello
# 代码仓库启动 go mod 依赖管理, 生成 go.mod 文件
go mod init github.com/link1st/link1st/workspaces/hello
# 下载依赖包
go get github.com/link1st/example
# 编写 main 文件
vim main.go
// Package main main 文件, go 多模块工作区演示代码
// 实现将输入的字符串反转输出并输出
package main
import (
"flag"
"fmt"
"github.com/link1st/example/stringutil"
)
var (
str = ""
)
func init() {
flag.StringVar(&str, "str", str, "输入字符")
flag.Parse()
}
func main() {
if str == "" {
fmt.Println("示例: go run main.go -str hello")
fmt.Println("str 参数必填")
flag.Usage()
return
}
// 调用公共仓库, 进行字符串反转
str = stringutil.Reversal(str)
// 输出反转后的字符串
fmt.Println(str)
return
}
> go run main.go -str "hello world"
dlrow olleh
# 回到工作根目录, 将 common 代码下载到本地进行添加新的功能
# 下载依赖的 example 包
git clone [email protected]:link1st/example.git
# 在 example 包中添加 字符串大学的功能
// Package stringutil stringutil
package stringutil
import (
"unicode"
)
// ToUpper 将字符串进行大写
func ToUpper(s string) string {
r := []rune(s)
for i := range r {
r[i] = unicode.ToUpper(r[i])
}
return string(r)
}
由于代码还在本地调试, 未提交 git 仓库中, 这个时候就需要用到 Go 多模块工作区的功能了。
进入项目根目录, 初始化我们现在正在开发的模块
# 初始化 go.work 文件
go work init ./hello ./example
# 查看 go.work 文件内容
cat go.work
go 1.18
use (
./example
./hello
)
func main() {
...
// 调用公共仓库, 进行字符串反转
str = stringutil.Reversal(str)
// 增加字符大写的功能
str = stringutil.ToUpper(str)
// 输出反转后的字符串
fmt.Println(str)
...
}
可以看到输出了反转并 大写 的字符串, 大写的函数功能只在本地, 未提交到 git 上, 这样我们就实现了可以同时在两个模块上并行开发
go run main.go -str "hello world"
DLROW OLLEH