在 Go 中,若需多个 worker 包共享同一结构体(如 ResultEvent),不应将其定义在 main 包中,而应提取到独立的、可导出的公共包(如 event 或 model)中,并通过首字母大写导出,供各包统一导入使用。
在 go 中,若需多个 worker 包共享同一结构体(如 `resultevent`),不应将其定义在 `main` 包中,而应提取到独立的、可导出的公共包(如 `event` 或 `model`)中,并通过首字母大写导出,供各包统一导入使用。
要实现结构体在多个 worker 包间安全、可维护地复用,核心原则是:
将共享类型定义在独立的、可导出的公共包中,而非 main 包
。main 包仅用于程序入口,其内部定义的类型无法被其他包访问,这与 Go 的包作用域机制严格相关。
✅ 正确做法:创建一个专用的共享模型包
例如,新建 model 包(路径如 your-module/model):
注意:字段名必须首字母大写(如 Name、Desc)才能被外部包导出访问;建议同时添加 JSON 标签以支持序列化。
随后,在 main 包和各 worker 包中统一导入并使用:
⚠️ 注意事项:
❌ 避免在 main 包中定义共享结构体——它不可导出,且 main 不能被其他包导入;
✅ 不推荐将结构体放在某个 worker 包中再让其他包反向导入(违反职责分离,易造成循环依赖或包耦合);
✅ 若项目规模扩大,可进一步按领域拆分共享包,如 model(数据结构)、event(事件契约)、dto(传输对象);
✅ 所有 worker 包应只依赖 model,不相互依赖,便于独立测试与替换。
总结:Go 的模块化设计鼓励“契约先行”——将跨包通信所需的结构体、接口等收敛到专用的、语义清晰的公共包中。这种结构不仅解决当前复用问题,更支撑未来扩展(如新增 50 个 worker)、类型安全校验及 API 一致性保障。
// model/event.go
package model
// ResultEvent 是所有 worker 包统一使用的响应结构体
type ResultEvent struct {
Name string `json:"name"`
Desc string `json:"desc"`
}// main.go
package main
import (
"your-module/model"
"your-module/worker"
)
func main() {
ch := make(chan model.ResultEvent, 10)
go func() {
worker.DoWork(ch)
}()
result := <-ch
println(result.Name) // 输出: test
}// worker/worker.go
package worker
import "your-module/model"
func DoWork(ch chan<- model.ResultEvent) {
result := model.ResultEvent{
Name: "test",
Desc: "processed by worker",
}
ch <- result // 安全发送:类型一致、包可见
}