在 Go 语言里,结构体中的嵌入类型(也叫匿名字段)是一种独特的特性,它能够让一个结构体 “继承” 另一个结构体或者接口的字段和方法。下面从定义、使用方式、访问规则、方法提升、注意事项等方面详细介绍。
在结构体中定义嵌入类型时,只需指定类型名,无需给出字段名。示例如下:
 
package main
import "fmt"
// 定义一个基础结构体
type Address struct {
    City    string
    Country string
}
// 定义一个包含嵌入类型的结构体
type Person struct {
    Name string
    Age  int
    Address
}
func main() {
    // 创建一个 Person 结构体实例
    p := Person{
        Name: "Alice",
        Age:  30,
        Address: Address{
            City:    "New York",
            Country: "USA",
        },
    }
    // 访问 Person 结构体的字段
    fmt.Printf("Name: %s, Age: %d, City: %s, Country: %s\n", p.Name, p.Age, p.City, p.Country)
}
 
Person 结构体嵌入了 Address 结构体,这样 Person 结构体的实例就可以直接访问 Address 结构体的字段。除此之外,也可以通过嵌入类型名显式访问其字段和方法。如下所示:
package main
import "fmt"
type Address struct {
    City    string
    Country string
}
type Person struct {
    Name string
    Age  int
    Address
}
func main() {
    p := Person{
        Name: "Bob",
        Age:  25,
        Address: Address{
            City:    "London",
            Country: "UK",
        },
    }
    // 直接访问
    fmt.Println(p.City)
    // 显式访问
    fmt.Println(p.Address.City)
}
 
Circle 结构体实现了 Shape 接口的 Area 方法,CircleInfo 结构体嵌入了 Circle 结构体,因此 CircleInfo 结构体的实例可以直接调用 Area 方法。
- 命名冲突:如果外层结构体和嵌入类型有同名的字段或方法,直接访问时会优先访问外层结构体的字段或方法。若要访问嵌入类型的同名成员,需要显式指定嵌入类型名。
- 多层嵌入:可以进行多层嵌入,即一个结构体嵌入另一个包含嵌入类型的结构体,但这会让代码的复杂度增加,需要谨慎使用。