在 go 中嵌入结构体时,选择指针嵌入(*t)还是值嵌入(t)需综合考虑方法集、内存布局、零值语义与性能;小而固定大小的结构体(如 [4][4]bool)通常推荐值嵌入以提升缓存局部性并避免额外分配。
嵌入是 Go 实现组合(composition)的核心机制,但嵌入方式直接影响行为语义和运行时表现。关键判断维度如下:
Go 的方法调用规则规定:只有接收者为 *T 的方法,才能被 *T 类型调用;而 T 类型只能调用接收者为 T 的方法。但嵌入后,外层类型能否调用被嵌入类型的方法,取决于外层值的“可寻址性”:
func (b *Bitmap) Render() { /* ... */ }
func (b Bitmap) Size() int { return len(b.data) * len(b.data[0]) }
// 嵌入值:
type Renderer struct {
Bitmap // 值嵌入
on, off uint8
}
func main() {
r := Renderer{}
r.Render() // ✅ OK:r 是可寻址的,Go 自动取 &r.Bitmap 调用 *Bitmap.Render
r.Size() // ✅ OK:直接调用值方法
}若 Bitmap 无意义的零值(例如含 sync.Mutex、*os.File 或需初始化的字段),或其构造函数明确返回 *Bitmap(如 NewBitmap() *Bitmap),则嵌入 *Bitmap 更安全——它天然规避了无效零值拷贝,并与使用者预期一致。
你示例中的 Bitmap 仅占 4

// 推荐:小结构体值嵌入 → 紧凑、高效
type Renderer struct {
Bitmap // ✅ data 直接位于 Renderer 内存中
on, off uint8
}
// 对比:指针嵌入 → 多一次间接寻址 + 堆分配风险
type RendererPtr struct {
*Bitmap // ❌ 需显式初始化:&Bitmap{},且 r.data 访问需解引用
on, off uint8
}综上,在你的具体场景([4][4]bool 小结构体、无复杂初始化逻辑)下,值嵌入是更优选择:它简洁、高效、符合 Go 的内存友好设计哲学,同时完全兼容常见使用模式。