嵌入字段的用法 #
以某个类型名、类型的指针类型名或接口类型名,直接作为结构体字段的方式就叫做结构体的类型嵌入,这些字段也被叫做嵌入字段(Embedded Field)。
我们结合具体的例子,简单说一下嵌入字段的用法:
type MyInt int
func (n *MyInt) Add(m int) {
*n = *n + MyInt(m)
}
type t struct {
a int
b int
}
type S struct {
*MyInt
t
io.Reader
s string
n int
}
func main() {
m := MyInt(17)
r := strings.NewReader("hello, go")
s := S{
MyInt: &m,
t: t{
a: 1,
b: 2,
},
Reader: r,
s: "demo",
}
var sl = make([]byte, len("hello, go"))
s.Reader.Read(sl)
fmt.Println(string(sl)) // hello, go
s.MyInt.Add(5)
fmt.Println(*(s.MyInt)) // 22
}
结构体中的嵌入的标识符,既代表字段的名字,也代表字段的类型。
为什么第三个嵌入字段的名字为 Reader 而不是 io.Reader?这是因为,Go 语言规定如果结构体使用从其他包导入的类型作为嵌入字段,比如 pkg.T,那么这个嵌入字段的字段名就是 T,代表的类型为 pkg.T。
嵌入字段的用法和普通字段很相似。不过,Go 对嵌入字段有一些约束的。比如,和 Go 方法的 receiver 的基类型一样,嵌入字段类型的底层类型不能为指针类型。而且,嵌入字段的名字在结构体定义也必须是唯一的,这也意味这如果两个类型的名字相同,它们无法同时作为嵌入字段放到同一个结构体定义中。