在管理多模块管理时,可能有的模块还在开发中,还没发布到github上,在Go 1.18之前是通过 go mod 的 replace 来做的。2022 年2 月份正式发布的 go1.18 由于新增了工作区特性,给多模块管理提供另一种更方便的解决途径。
过去的replace模式
hanwei@hanweideMacBook-Air golang]$ go version
go version go1.18 darwin/arm64
hanwei@hanweideMacBook-Air golang]$ mkdir go1.18-workspace/
hanwei@hanweideMacBook-Air golang]$ cd go1.18-workspace/
hanwei@hanweideMacBook-Air go1.18-workspace]$ mkdir mypkg example
hanwei@hanweideMacBook-Air go1.18-workspace]$ tree
.
├── example
└── mypkg
2 directories, 0 files
hanwei@hanweideMacBook-Air go1.18-workspace]$ go mod init github.com/go1.18-workspace/mypkg
go: creating new go.mod: module github.com/go1.18-workspace/mypkg
go: to add module requirements and sums:
go mod tidy
hanwei@hanweideMacBook-Air go1.18-workspace]$ cd mypkg/
hanwei@hanweideMacBook-Air mypkg]$ touch bar.go
hanwei@hanweideMacBook-Air mypkg]$ vi bar.go
hanwei@hanweideMacBook-Air mypkg]$ cat bar.go
package mypkg
func Bar() {
println("This is package mypkg")
}
hanwei@hanweideMacBook-Air mypkg]$ cd ../example/
hanwei@hanweideMacBook-Air example]$ go mod init github.com/go1.18-workspace/example
go: creating new go.mod: module github.com/go1.18-workspace/example
go: to add module requirements and sums:
go mod tidy
hanwei@hanweideMacBook-Air example]$ touch main.go
hanwei@hanweideMacBook-Air example]$ vi main.go
hanwei@hanweideMacBook-Air example]$ cat main.go
package main
import (
"github.com/go1.18-workspace/mypkg"
)
func main() {
mypkg.Bar()
}
这时候,如果我们运行 go mod tidy,肯定会报错,因为我们的 mypkg 包根本没有提交到 github 上,肯定找不到。
hanwei@hanweideMacBook-Air example]$ go mod tidy
go: finding module for package github.com/go1.18-workspace/mypkg
github.com/go1.18-workspace/example imports
github.com/go1.18-workspace/mypkg: cannot find module providing package github.com/go1.18-workspace/mypkg: module github.com/go1.18-workspace/mypkg: git ls-remote -q origin in /Users/hanwei/GoProjects/pkg/mod/cache/vcs/2c423cac5ebc1b2d018ef93a87560d369abd7dec6c155b46cddb11299415bc09: exit status 128:
remote: Repository not found.
fatal: repository 'https://github.com/go1.18-workspace/mypkg/' not found
hanwei@hanweideMacBook-Air example]$ go run main.go
main.go:4:5: no required module provides package github.com/go1.18-workspace/mypkg; to add it:
go get github.com/go1.18-workspace/mypkg
go run main.go 也就不成功。
我们当然可以提交 mypkg 到 github,但我们每修改一次 mypkg,就需要提交,否则 example 中就没法使用上最新的。
针对这种情况,目前是建议通过 replace 来解决,即在 example 中的 go.mod 增加如下 replace:
hanwei@hanweideMacBook-Air example]$ go mod edit -replace=github.com/go1.18-workspace/mypkg=../mypkg
hanwei@hanweideMacBook-Air example]$ cat go.mod
module github.com/go1.18-workspace/example
go 1.18
replace github.com/go1.18-workspace/mypkg => ../mypkg
(v1.0.0 根据具体情况修改,还未提交,可以使用 v1.0.0)
hanwei@hanweideMacBook-Air example]$ cat go.mod
module github.com/go1.18-workspace/example
go 1.18
require github.com/go1.18-workspace/mypkg v1.0.0
replace github.com/go1.18-workspace/mypkg => ../mypkg
hanwei@hanweideMacBook-Air example]$ tree ..
..
├── example
│ ├── go.mod
│ └── main.go
└── mypkg
├── bar.go
└── go.mod
2 directories, 4 files
再次运行 go run main.go,输出如下:
hanwei@hanweideMacBook-Air example]$ go run main.go
This is package mypkg
工作区模式
将上面的replace注释,再执行go run main.go,报错
hanwei@hanweideMacBook-Air example]$ cat go.mod
module github.com/go1.18-workspace/example
go 1.18
//require github.com/go1.18-workspace/mypkg v1.0.0
//replace github.com/go1.18-workspace/mypkg => ../mypkg
hanwei@hanweideMacBook-Air example]$ go run main.go
main.go:4:5: missing go.sum entry for module providing package github.com/go1.18-workspace/mypkg; to add:
go mod download github.com/go1.18-workspace/mypkg
初始化 workspace
hanwei@hanweideMacBook-Air go1.18-workspace]$ go version
go version go1.18 darwin/arm64
hanwei@hanweideMacBook-Air go1.18-workspace]$ go work init example mypkg
hanwei@hanweideMacBook-Air go1.18-workspace]$ tree
.
├── example
│ ├── go.mod
│ └── main.go
├── go.work
└── mypkg
├── bar.go
└── go.mod
2 directories, 5 files
hanwei@hanweideMacBook-Air go1.18-workspace]$ cat go.work
go 1.18
use (
./example
./mypkg
)
hanwei@hanweideMacBook-Air example]$ go run main.go
This is package mypkg
可见用工作区比replace方便太多了。
go.work 文件的语法和 go.mod 类似,因此也支持 replace。
注意,go.work 不需要提交到 Git 中,因为它只是本地开发使用的。
cat .gitignore
# ---> Go
# If you prefer the allow list template instead of the deny list, see community template:
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
#
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Dependency directories (remove the comment below to include it)
# vendor/
# Go workspace file
go.work
在 GOPATH 年代,多 GOPATH 是一个头疼的问题。当时没有很好的解决,Module 就出现了,多 GOPATH 问题因此消失。但多 Module 问题随之出现。Workspace 方案较好的解决了这个问题。
转载请注明来源,欢迎指出任何有错误或不够清晰的表达。可以邮件至 backendcloud@gmail.com