Golang初级系列教程-结构体匿名字段-Anonymous fields in structs

来源:互联网 发布:c语言中的int 编辑:程序博客网 时间:2024/05/22 18:23

Golang初级系列教程-结构体匿名字段-Anonymous fields in structs

Go 结构体中支持匿名字段。下面的几个例子中,会展示如何构造以及这种用法的好处。

下面的代码中,定义了结构体 Kitchen,包含字段 numOfPlates。另一个结构体 House,包含 Kitchen 的一个实例,但是没有变量名——即匿名。

package mainimport "fmt"type Kitchen struct {    numOfPlates int}type House struct {    Kitchen //anonymous field    numOfRooms int}func main() {    h := House{Kitchen{10}, 3} //to initialize you have to use composed type name.    fmt.Println("House h has this many rooms:", h.numOfRooms) //numOfRooms is a field of House    fmt.Println("House h has this many plates:", h.numOfPlates) //numOfPlates is a field of anonymous field Kitchen, so it can be referred to like a field of House    fmt.Println("The Kitchen contents of this house are:", h.Kitchen) //we can refer to the embedded struct in its entirety by referring to the name of the struct type}
House h has this many rooms: 3House h has this many plates: 10The Kitchen contents of this house are: {10}

首先需要强调的一点是,由于 KitchenHouse 的匿名字段,House 可以访问 Kitchen 的属性,就如同这些属性是 House 本身的一样。为了说明这一点,让我们同 Java 代码做一个对比。

public class Kitchen {    public int numOfPlates;}public class House {    public Kitchen kitchen;}//and in mainpublic static void main(String[] args) {    House h = new House();    h.kitchen.numOfPlates = 10; //referred as a sub field item.}

其次,匿名字段通过其类型名也可以访问。所以,对于上面的的例子,可以通过 h.kitchen 访问,这时打印盘子个数应该写为 fmt.Println(h.Kitchen.numOfPlates)

第三点,定义时,必须使用类型名,如同上面所示 h := House{Kitchen{10}, 3}。如果不写上类型和其对应的 {},如同下面的两种定义方式都会产生编译错误,h := House{{10}, 3}h := House{10, 3}

匿名类型命名冲突

当匿名字段包含相同的字段命名或者外围结构体含有和匿名结构相同的字段名时,程序会如何运行?当外围结构体含有和匿名结构相同的字段时,默认访问外围结构体的字段。下面的代码中,kitchenHouse 都有个字段名为 numOfLamps,由于 House 包含 kitchen ,所以 HousenumOfLamps 会覆盖 kitchen 的。如果想访问 kitchennumOfLamps ,则需要通过使用类型名 h.Kitchen.numOfLamps

package mainimport "fmt"type Kitchen struct {    numOfLamps int}type House struct {    Kitchen    numOfLamps int}func main() {    h := House{Kitchen{2}, 10} //kitchen has 2 lamps, and the House has a total of 10 lamps    fmt.Println("House h has this many lamps:", h.numOfLamps) //this is ok - the outer House's numOfLamps hides the other one.  Output is 10.    fmt.Println("The Kitchen in house h has this many lamps:", h.Kitchen.numOfLamps) //we can still reach the number of lamps in the kitchen by using the type name h.Kitchen}
House h has this many lamps: 10The Kitchen in house h has this many lamps: 2

所以,当结构体不同级组合遇到命名冲突时,存在字段的解析规则。但是,对于同一级的结构体字段命名冲突,程序无法完成解析——需要自行解决。

下面代码中,KitchenBedroom 都包含 numOfLamps 字段,并且都是 House 的匿名字段。当访问 House.numOfLamps 时,Go 编译器不知道是访问哪个,进而抛出错误。

package mainimport "fmt"type Kitchen struct {    numOfLamps int}type Bedroom struct {    numOfLamps int}type House struct {    Kitchen    Bedroom}func main() {    h := House{Kitchen{2}, Bedroom{3}} //kitchen has 2 lamps, Bedroom has 3 lamps    fmt.Println("Ambiguous number of lamps:", h.numOfLamps) //this is an error due to ambiguousness - is it Kitchen.numOfLamps or Bedroom.numOfLamps}
8g -o _go_.8 structs2.gostructs2.go:20: ambiguous DOT reference House.numOfLampsmake: *** [_go_.8] Error 1

只能通过使用类型名的方式进行访问,如下面代码所示。

package mainimport "fmt"type Kitchen struct {    numOfLamps int}type Bedroom struct {    numOfLamps int}type House struct {    Kitchen    Bedroom}func main() {    h := House{Kitchen{2}, Bedroom{3}}    fmt.Println("House h has this many lamps:", h.Kitchen.numOfLamps + h.Bedroom.numOfLamps) //refer to fields via type name}
House h has this many lamps: 5

Golang一种神奇的语言,让我们一起进步

0 0
原创粉丝点击