结构体可以包含一个或多个匿名(或内嵌)字段,即这些字段没有显式的名字,只有字段的类型是必须的,此时类型也就是字段的名字。匿名字段本身可以是一个结构体类型,即结构体可以包含内嵌结构体。 可以粗略地将这个和面向对象语言中的继承概念相比较,随后将会看到它被用来模拟类似继承的行为。Go语言中的继承是通过内嵌或组合来实现的,所以可以说,在Go语言中,相比较于继承,组合更受青睐。 考虑如下的程序: packagemain importfmt typeinnerSstruct{ in1int in2int } typeouterSstruct{ bint cfloat32 intanonymousfield innerSanonymousfield } funcmain(){ outer:new(outerS) outer。b6 outer。c7。5 outer。int60 outer。in15 outer。in210 fmt。Printf(outer。bis:d,outer。b) fmt。Printf(outer。cis:f,outer。c) fmt。Printf(outer。intis:d,outer。int) fmt。Printf(outer。in1is:d,outer。in1) fmt。Printf(outer。in2is:d,outer。in2) 使用结构体字面量 outer2:outerS{6,7。5,60,innerS{5,10}} fmt。Printf(outer2is:,outer2) } 运行结果如下所示: outer。bis:6 outer。cis:7。500000 outer。intis:60 outer。in1is:5 outer。in2is:10 outer2is:{67。560{510}} 通过类型outer。int的名字来获取存储在匿名字段中的数据,于是可以得出一个结论:在一个结构体中对于每一种数据类型只能有一个匿名字段。 内嵌结构体 同样地结构体也是一种数据类型,所以它也可以作为一个匿名字段来使用,如同上面例子中那样。外层结构体通过outer。in1直接进入内层结构体的字段,内嵌结构体甚至可以来自其他包。内层结构体被简单的插入或者内嵌进外层结构体。这个简单的继承机制提供了一种方式,使得可以从另外一个或一些类型继承部分或全部实现。 示例代码如下所示: packagemain importfmt typeAstruct{ ax,ayint } typeBstruct{ A bx,byfloat32 } funcmain(){ b:B{A{1,2},3。0,4。0} fmt。Println(b。ax,b。ay,b。bx,b。by) fmt。Println(b。A) } 输出: 1234 {12} 结构内嵌特性 Go语言的结构体内嵌有如下特性。 1)内嵌的结构体可以直接访问其成员变量 嵌入结构体的成员,可以通过外部结构体的实例直接访问。如果结构体有多层嵌入结构体,结构体实例访问任意一级的嵌入结构体成员时都只用给出字段名,而无须像传统结构体字段一样,通过一层层的结构体字段访问到最终的字段。例如,ins。a。b。c的访问可以简化为ins。c。 2)内嵌结构体的字段名是它的类型名 内嵌结构体字段仍然可以使用详细的字段进行一层层访问,内嵌结构体的字段名就是它的类型名,代码如下: varcColor c。BasicColor。R1 c。BasicColor。G1 c。BasicColor。B0 一个结构体只能嵌入一个同类型的成员,无须担心结构体重名和错误赋值的情况,编译器在发现可能的赋值歧义时会报错。