golang ---struct
package main
import (
"fmt"
)
func main() {
type Point struct {
X, Y int
}
type Circle struct {
Point
Radius int
}
type Wheel struct {
Circle
Spokes int
}
var w Wheel
//w = Wheel{Circle{Point{8, 8}, 5}, 20}
w = Wheel{
Circle: Circle{
Point: Point{X: 8, Y: 8},
Radius: 5,
},
Spokes: 20, // NOTE: trailing comma necessary here (and at Radius)
}
fmt.Printf("%#v\n", w)
// Output:
// Wheel{Circle:Circle{Point:Point{X:8, Y:8}, Radius:5}, Spokes:20}
w.X = 42
w.Y = 48
w.Radius = 10
w.Spokes = 30
fmt.Printf("%#v\n", w)
// Output:
// Wheel{Circle:Circle{Point:Point{X:42, Y:8}, Radius:5}, Spokes:20}
}
结果输出:需要注意的是Printf函数中%v参数包含的#副词,它表示用和Go语言类似的语法打印值。对于结构体类型来说,将包含每个成员的名字。
main.Wheel{Circle:main.Circle{Point:main.Point{X:8, Y:8}, Radius:5}, Spokes:20} main.Wheel{Circle:main.Circle{Point:main.Point{X:42, Y:48}, Radius:10}, Spokes:30}
Go语言有一个特性让我们只声明一个成员对应的数据类型而不指名成员的名字;这类成员就
叫匿名成员。匿名成员的数据类型必须是命名的类型或指向一个命名的类型的指针。上面的
代码中,Circle和Wheel各自都有一个匿名成员。我们可以说Point类型被嵌入到了Circle结构
体,同时Circle类型被嵌入到了Wheel结构体。
得意于匿名嵌入的特性,我们可以直接访问叶子属性而不需要给出完整的路径,如:
var w Wheel w.X = 8 // equivalent to w.Circle.Point.X = 8 w.Y = 8 // equivalent to w.Circle.Point.Y = 8 w.Radius = 5 // equivalent to w.Circle.Radius = 5 w.Spokes = 20
其中匿名成员Circle和Point都有自己的名字——就是命名的类型名字——但是
这些名字在点操作符中是可选的。我们在访问子成员的时候可以忽略任何匿名成员部分。
不幸的是,结构体字面值并没有简短表示匿名成员的语法, 因此下面的语句都不能编译通
过:
w = Wheel{8, 8, 5, 20} // compile error: unknown fields w = Wheel{X: 8, Y: 8, Radius: 5, Spokes: 20} // compile error: unknown fields
结构体字面值必须遵循形状类型声明时的结构
//w = Wheel{Circle{Point{8, 8}, 5}, 20} w = Wheel{ Circle: Circle{ Point: Point{X: 8, Y: 8}, Radius: 5, }, Spokes: 20, // NOTE: trailing comma necessary here (and at Radius) }