返回 MyStruct 是因接口方法含指针接收者,只有 T 能实现该接口;值类型 T 无法满足,会导致编译错误。

Go 语言没有类和继承,所谓“工厂模式”本质是用函数返回接口类型值,而指针在这里的作用不是为了模拟 OOP,而是控制数据所有权、避免拷贝、满足接口实现条件——如果你试图用指针“new 一个结构体再赋值给接口”,却忘了该结构体是否实现了接口,或者误传了值类型导致接口不满足,那就踩坑了。
为什么返回 *MyStruct 而不是 MyStruct?
Go 接口的实现是隐式的,但有关键规则:如果接口方法集包含指针接收者,则只有 *T 类型能实现该接口,T 值类型不能。工厂函数若返回值类型,而你的方法定义在 *T 上,调用方拿到的值会无法满足接口。
- 常见错误现象:
cannot use myStruct{} (type MyStruct) as type Worker in return argument: MyStruct does not implement Worker (Do method has pointer receiver) - 使用场景:结构体含字段需被方法修改(如状态计数器)、或结构体较大(避免复制开销)
- 性能影响:小结构体(如仅几个 int)传值更高效;大结构体(含 slice/map/chan 或大量字段)用指针更合理
NewWorker 工厂函数必须返回指针吗?
不一定。取决于你定义的接口方法接收者类型。如果所有方法都是值接收者,NewWorker() 可安全返回 Worker(即 MyStruct),但这样无法在方法中修改原始结构体字段。
- 示例对比:
type Worker interface { Do() } type concreteWorker struct { count int } func (c concreteWorker) Do() { c.count++ } // 值接收者 → 修改无效 func (c *concreteWorker) Do() { c.count++ } // 指针接收者 → 修改生效 func NewWorker() Worker { return concreteWorker{} } // ✅ 满足接口,但 Do 不改变原值 func NewWorker() Worker { return &concreteWorker{} } // ✅ 满足接口,Do 可修改字段 - 参数差异:
NewWorker()本身不接受参数时,指针与否只影响返回值语义;若需初始化字段(如NewWorker(name string)),通常直接构造并取地址更自然
工厂内部是否该用 &{...} 还是 new(T)?
优先用 &MyStruct{field: value}。它明确、可读、支持字段初始化;new(MyStruct) 只返回零值指针,后续还得手动赋值,易遗漏且无编译检查。
立即学习“go语言免费学习笔记(深入)”;
- 容易踩的坑:
new(MyStruct)返回的是所有字段为零值的指针,若忘记初始化关键字段(如依赖的http.Client),运行时 panic - 使用场景:当结构体字段多、部分可选时,推荐用选项函数(functional options)配合指针构造,而不是裸写
&{...} - 兼容性影响:两者都生成合法指针,但
&{...}在字段顺序变更时更脆弱(除非命名初始化),建议始终显式命名字段
真正容易被忽略的点是:工厂返回的指针类型是否真的实现了你要的接口——这不靠文档或注释保证,而靠编译器报错。别假设“我写了指针接收者,就一定行”,要实际让返回值赋给接口变量,让编译器说话。









