登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  Golang >  Go教程

Go go work use 怎样把多个模块加入工作区

来源:17golang原创

时间:2026-10-26 17:27:40 288浏览 收藏

在工作区目录中先用 go work init 创建 go.work,再执行 go work use ./checkout ./pricekit,就能把两个模块同时加入工作区。传入的应是包含各自 go.mod 的目录,不是 module 声明中的导入路径;已有 go.work 时直接 use 即可。

例如结算应用 checkout 与计价库 pricekit 分属两个模块,同一改动需要两边联调。工作区让本地库可以直接参与构建,减少反复修改本地 replace 的操作。但这种便利只说明本机组合可以工作,还不能说明模块发布后也能独立解析依赖。

Go 官方地址:https://go.dev/

先确定要一起开发哪些模块

这里选择一个应用模块和一个库模块。目录名用来定位磁盘位置,module path 用来写 import;这两种名字可以不同。每个模块继续维护自己的 go.mod,工作区不会把它们合并成单个模块,也不会替你建立可发布版本。

对象作用
checkout/go.mod声明结算应用模块
pricekit/go.mod声明计价库模块
go.work 中的 use选择参与当前工作区的本地模块目录
import 路径让 Go 代码引用计价库包

这适合跨模块修改尚未发布的接口。只有一个模块时,单纯为了建立一份 go.work 而建立工作区通常没有额外收益。本文不以搜索量或流行程度作判断,重点是联调成本与发布可重现性这两个实际条件。

准备两个各自独立的模块

以下是可自行复现的最小示例,命令按 POSIX shell 写法给出;正文没有把示例描述为已在本机执行的结果。先在新目录中创建两个模块:

# 在新演示目录中创建两个模块,避免改变现有项目
mkdir -p checkout-workspace/checkout checkout-workspace/pricekit
cd checkout-workspace
cd checkout
go mod init example.com/checkout
cd ../pricekit
go mod init example.com/pricekit
cd ..

把下面内容保存为 pricekit/price.go。例子用整数分作为金额单位,只做固定单价乘数量,避免把模块管理话题扩展成实际计费系统。

package pricekit

// TotalCents 用整数分计算示例总价,调用方应传入非负数量。
func TotalCents(quantity int) int {
    return quantity * 1250
}

再把下面内容保存为 checkout/main.go。import 引用的是 pricekit 模块的根包,不是相对磁盘路径。

package main

import (
    "fmt"
    "example.com/pricekit"
)

func main() {
    // 工作区中的本地库提供计价函数,数量为示例常量。
    total := pricekit.TotalCents(3)
    fmt.Printf("total_cents=%d\n", total)
}

初始化工作区,再把模块目录加入 use

# 从 checkout-workspace 目录创建工作区并加入两个模块根目录
go work init
go work use ./checkout ./pricekit
# 显示当前命令实际使用的工作区文件
go env GOWORK

成功后,go.work 的 use 块应包含 ./checkout 与 ./pricekit。go 指令由本机 Go 工具生成,不需要照抄文章中的版本号。执行 go env GOWORK 时,读者应看到刚创建的 go.work 的路径;为空或指向别处时,先检查运行目录和 GOWORK 环境设置。

已经创建过工作区,不要再次运行 init 覆盖配置,直接追加 use 参数即可。相对路径记录在工作区上下文中,移动项目后应重新确认目录是否仍能对应。

工作区use配置与两个模块根目录的关系
图1:模块成员结构图。工作区包含两个模块目录,每个目录保留自己的 go.mod;图中连线表示配置归属和包引用,不表示执行顺序。

从明确的模块路径构建,观察本地修改

# 在工作区根目录运行指定应用,不把根目录假定为模块
go run ./checkout
# 分别选择两个模块中的包,供读者检查构建与测试
go test ./checkout/... ./pricekit/...

按示例逻辑,应用会打印 total_cents=3750;这是代码推导出的预期值,不是实测日志。若把库中的固定单价改成其他数值,重新运行应用应反映本地修改,说明联调目标确实是工作区内的库。

工作区根目录可以没有 go.mod,因此不要直接把根目录下的 ./... 当成“自动覆盖所有成员”的通用写法。显式列出成员路径,能更清楚地表达希望构建哪些包。没有测试文件时,go test 只完成相应包的构建等工作,不能称为业务断言全部通过。

若提示找不到库,先核对 pricekit/go.mod 的 module 声明是否与 import 一致,再核对 use 中是否是模块根目录。仅把仓库父目录加入 use,并不会自动包含其中的全部嵌套模块。

模块很多时怎样递归加入和移除

# 明确需要收集当前目录树内模块时,才采用递归方式
go work use -r .
# 不再参与联调时,仅移除工作区成员,不删除源码目录
go work edit -dropuse=./pricekit

-r 会递归查找模块目录,适合已经梳理过目录范围的项目。若目录里还有演示、工具或其他嵌套模块,递归加入会扩大联调集合;模块少时显式列出路径更容易审阅。移除 pricekit 后,这个应用示例就不能继续依靠它的工作区成员身份解析导入,需要重新加入,或建立正常的可下载版本依赖。

这里不把 go work sync 当作加入成员的必要步骤。sync 涉及将工作区选出的依赖版本同步回成员模块,可能改动 go.mod;只想添加本地模块时,用 use 就能表达目的。

让工作区联调与独立发布各自成立

use 是本地开发组合,不等于 checkout 已经声明了可以独立获取的 pricekit 版本。本文两个 example.com 路径仅为演示,没有发布仓库。准备真实发布时,应在实际模块路径上发布可获取版本,并在调用模块中维护正常依赖,而不能把 go.work 当作下游用户的依赖声明。

本地联调与独立模块发布的配置边界
图2:开发与发布结构图。本地联调使用工作区成员,独立模块依赖 go.mod 和可获取版本;两侧配置服务于不同环境。
# 在真实应用模块目录中关闭工作区,观察独立依赖是否完整
cd checkout
GOWORK=off go test ./...

对本文尚未发布库、未声明 require 的演示,这条独立检查预期会遇到缺少依赖的问题;它揭示的是演示的发布边界,不应通过继续打开工作区把问题掩盖掉。真实项目完成版本发布和依赖声明后,再观察独立模式能否通过。

普通可独立消费的模块,应避免让个人工作区无意影响 CI;如果仓库的多个模块约定只以固定组合共同开发,也可以明确管理 go.work,但团队仍要记录成员范围与发布策略。采用是否合适,可以看本地 replace 修改是否减少、成员路径是否稳定、独立模块的依赖检查是否仍能成立。

use 能写 example.com/pricekit 吗?

它接收模块所在目录。此例应写 ./pricekit;example.com/pricekit 用于 module 和 import,不是这里的目录参数。

为什么子目录运行也会用到工作区?

没有显式指定 GOWORK 时,Go 会从当前目录向父目录查找 go.work。若不确定命中了哪一份,使用 go env GOWORK 查看。

go.work 必须提交仓库吗?

不必须。个人跨仓库联调通常保留个人组合;固定多模块项目则由团队明确决定。关键是不能让一份本地组合掩盖模块真实依赖缺失。

命令规则与环境选择参见 Go 模块参考文档;工作区协作方式参见 Go 官方多模块工作区教程。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>