go入门练习006:struct
struct基本概念
定义:字段顺序非常重要!两个字段完全一样,但顺序不同的struct视为不同。
type Employee struct {
ID int
Name string
Address string
DoB time.Time
Position string
Salary int
ManagerID int
}
使用:
var dilbert Employee
dilbert.Salary -= 5000
//指针访问
var employeeOfTheMonth *Employee = &dilbert
employeeOfTheMonth.Position += " (proactive team player)"
(*employeeOfTheMonth).Position += " (proactive team player)"
//dilbert的字段也是变量,也支持指针访问
position := &dilbert.Position
*position = "Senior " + *position
go函数传参基本上都是值传递,struct也是。
func Scale(p Point, factor int) Point {
return Point{p.X * factor, p.Y * factor}
}
所以,为了效率,通常使用指针:
func Bonus(e *Employee, percent int) int {
return e.Salary * percent / 100
}
struct不能嵌套定义,如结构体S,不能包含S字段。但可以包含*S字段,这样就可以实现链表和树等数据结构了。
package main
import "fmt"
type tree struct {
value int
left, right *tree
}
// Sort sorts values in place.
func Sort(values []int) {
var root *tree
for _, v := range values {
root = add(root, v)
}
appendValues(values[:0], root)
}
// appendValues appends the elements of t to values in order
// and returns the resulting slice.
func appendValues(values []int, t *tree) []int {
if t != nil {
values = appendValues(values, t.left)
values = append(values, t.value)
values = appendValues(values, t.right)
}
return values
}
func add(t *tree, value int) *tree {
if t == nil {
// 相当于 return &tree{value: value}.
t = new(tree)
t.value = value
return t
}
if value < t.value {
t.left = add(t.left, value)
} else {
t.right = add(t.right, value)
}
return t
}
func main() {
values := []int{1, 5, 0, 6, 7, 1, 6, 7, 3, 7, 0}
Sort(values)
fmt.Println(values)
}
struct字面量
struct字面量有两种形式:
type Point struct{ X, Y int }
//方式1,按位置
p := Point{1, 2}
//方式2,按字段名
p := Point{X:1,Y:2}
//显然方式2更灵活,可以省略部分字段,省略的字段默认零值
p := Point{Y:2}
由于struct经常用指针,go提供了一个简便的方式来创建和初始化struct并获取它的指针:
pp := &Point{1, 2}
//等价于
pp := new(Point)
*pp = Point{1, 2}
struct嵌套和匿名字段
struct嵌套采用组合的思想,简化struct的定义,如两个struct:
type Circle struct {
X, Y, Radius int
}
type Wheel struct {
X, Y, Radius, Spokes int
}
轮子Wheel前三个字段都是圆Circle的字段,因此可以嵌套定义:
type Point struct {
X, Y int
}
type Circle struct {
Center Point//圆心
Radius int
}
type Wheel struct {
Circle Circle//圆
Spokes int
}
var w Wheel
w.Circle.Center.X = 8
w.Circle.Center.Y = 8
w.Circle.Radius = 5
w.Spokes = 20
上面访问Wheel字段的方式非常繁琐,使用匿名字段可以简化:
type Circle struct {
Point//匿名字段圆心
Radius int
}
type Wheel struct {
Circle//匿名字段圆
Spokes int
}
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
匿名字段的问题是不支持字面量:
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)
}