Go多模块项目需按功能拆分为独立模块(如api/、service/),各设go.mod;根模块仅作版本锚点,用replace本地开发、require统一管理;严禁循环依赖,接口应置于shared/;CI构建须进子目录执行。

在 Go 中初始化多模块项目,核心是避免单一 go.mod 文件管理整个大型代码库,转而按功能或服务边界拆分为多个独立模块(每个模块有自己 go.mod),再通过 replace、require 和目录结构设计实现依赖协同。
明确模块边界,按职责划分目录
不要把所有代码塞进一个 cmd 或 internal 下。推荐顶层按业务/能力分模块:
-
api/:提供 HTTP/gRPC 接口,含自己的go.mod -
service/:核心业务逻辑,可被多个 api 复用 -
data/:数据访问层(ORM、DB client 封装) -
shared/:跨模块通用类型、错误定义、工具函数 -
cmd/app1/、cmd/app2/:可独立部署的服务入口
每个子目录运行 go mod init example.com/project/api 初始化为独立模块,模块路径需全局唯一且反映实际导入路径。
主模块统一协调依赖版本
通常设一个“根模块”(如项目根目录的 go.mod),不写业务代码,只做版本锚点和跨模块引用管理:
CPWEB企业网站管理系统(以下称CPWEB)是一个基于PHP+Mysql架构的企业网站管理系统。CPWEB 采用模块化方式开发,功能强大灵活易于扩展,并且完全开放源代码,面向大中型站点提供重量级企业网站建设解决方案。CPWEB企业网站管理系统 2.2 Beta 测试版本,仅供测试,不建议使用在正式项目中,否则发生任何的后果自负。
立即学习“go语言免费学习笔记(深入)”;
- 在根
go.mod中require所有子模块(如example.com/project/service v0.0.0) - 用
replace指向本地路径,开发时实时生效:replace example.com/project/service => ./service - 发布前删掉
replace,打 tag 后go mod tidy自动升级为语义化版本
避免循环依赖与隐式耦合
Go 模块间不能循环 import,这是编译时报错的硬约束。常见陷阱:
-
service依赖data✅,但data又反向依赖service❌ -
解决方法:提取接口到
shared/interface,让data仅依赖接口,service实现它 - 禁止跨模块直接引用
internal/—— 它只对本模块可见;对外暴露必须通过public/或根包导出
CI/CD 和发布时保持一致性
多模块项目上线前需确保各模块版本锁定且可复现:
- 每个模块的
go.sum单独维护,根模块不覆盖子模块校验和 - 构建命令建议进入子模块目录执行:
cd cmd/app1 && go build -o app1 - CI 中可先
go mod vendor各模块(非必需,但利于离线构建),或统一用go build -mod=readonly防意外修改go.mod









