
本文讲解 go 中结构体嵌入与赋值的核心原理,解决“无法直接将 struct 赋值给含嵌入字段的 struct”这一常见编译错误,并提供正确、安全的字段复制方式。
本文讲解 go 中结构体嵌入与赋值的核心原理,解决“无法直接将 struct 赋值给含嵌入字段的 struct”这一常见编译错误,并提供正确、安全的字段复制方式。
在 Go 语言中,destination 并非 origin 的别名或同类型结构体,而是一个独立类型,仅通过嵌入(embedding)获得了 origin 的字段和方法提升(method promotion)。因此,尽管 destination 包含一个匿名字段 origin,它本身仍是 destination 类型——这正是编译器报错 cannot use theOrigin (type origin) as type destination in assignment 的根本原因:
*dest = theOrigin // ❌ 错误:origin ≠ destination,类型不兼容
✅ 正确做法是显式赋值给嵌入字段。由于嵌入字段的名称默认为其类型名(即 origin),应使用点号语法定位并赋值:
func (dest *destination) LaunchTheDevice(theOrigin origin) {
dest.origin = theOrigin // ✅ 正确:将 origin 值复制给嵌入字段
}
完整可运行示例(已修复):
package main
import "fmt"
type intf interface {
SaySomething(string)
LaunchTheDevice(origin)
}
type destination struct {
origin // 嵌入字段,类型为 origin
}
func (dest *destination) SaySomething(s string) {
fmt.Println("I'm saying --> ", s)
}
func (dest *destination) LaunchTheDevice(theOrigin origin) {
dest.origin = theOrigin // 关键修正:赋值给嵌入字段 origin
}
type origin struct {
name string
value string
infos string
}
func main() {
firstValue := &origin{
name: "Nyan",
value: "I'm the only one",
infos: "I'm a cat",
}
secondValue := &destination{}
secondValue.LaunchTheDevice(*firstValue)
// 验证字段已成功复制
fmt.Printf("Name: %s, Value: %s, Infos: %s\n",
secondValue.name, secondValue.value, secondValue.infos)
// 输出:Name: Nyan, Value: I'm the only one, Infos: I'm a cat
}
⚠️ 注意事项:
- 不要尝试
*dest = destination{origin: theOrigin}—— 这虽能编译,但属于冗余构造,且在destination含其他字段时易出错; - 若需深度复制(如嵌入字段含指针或 map/slice),应手动逐字段复制或使用
reflect/第三方库(如copier),但本例中origin是纯值类型,直接赋值即安全; - 方法接收者
*destination允许修改其嵌入字段,这是 Go 嵌入机制的设计优势。
总结:Go 的嵌入不是类型继承,而是组合 + 字段/方法提升。对嵌入字段的操作必须明确作用于该字段本身(dest.origin),而非整个宿主结构体(*dest)。理解这一点,即可避免绝大多数嵌入赋值类错误。











