赞
踩
struct 是一种聚合数据类型,将 0 个或多个任意类型的命名值组合成一个单个实体。其中的每个值都称为 field。
type Empoloyee struct {
ID int
Name string
Address string
DoB time.Time
Position string
Salary int
ManagerID int
}
var dilbert Employee
field 的顺序对于 struct 来说是有意义的,不同的 field 顺序表示不同的 struct 类型。
struct 通常出现在命名类型,比如 Empoloyee,的声明中。
命名结构体类型 S 不能声明一个 S 类型的 field:一个聚合值不能包含它自己。但是 S 可以声明一个类型为 S* 的指针类型 field。
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) valuse = appendValues(values, t.right) } return values } func add(t *tree, value int) *tree { if t == nil { // Equivalent to 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 }
stuct 的 zero value 是各 field 的 zero value 的组合。
struct 类型的值可以由 struct literal 进行写值,struct literal 有两种格式:
第一种格式如下,需要指定按顺序
各个 field 的值,结构体定义一旦修改,就必须对应修改。
type Point struct { X, Y int }
p := Point{1, 2} // struct literal
第二种格式列出 field names 和其对应的值的列表,如下所示:
anim := gif.GIF{LoopCount: nframes}
未列出的 field names 使用缺省值(zero value)。
不能被其他 package 访问的 field 不能在其他 package 中进行写值:
package p
type T struct{a, b int} // a and b are not exported
package q
import "p"
var _ = p.T{a: 1, b: 2} // compile error: can't reference a, b
var _ = p.T{1, 2} // complie error: can't reference a, b
直接构造结构体的指针:
pp := &Point{1, 2}
等价于:
pp := new(Point)
*pp = Point{1, 2}
使用 dot 符号访问成员:
dilbert.Salary -= 5000
或者进行取址通过指针进行访问:
position := &dilbert.Position
*position = "Senior" + *position
dot 符号对结构体指针依然有效:
var employeeOfTheMonth *Employee = &dilbert
employeeOfTheMonth.Position += " (proactive team player)"
最后一句等价于
(*employeeOfTheMonth).Position += " (proactive team player)"
可以将相同类型的连续字段写成一行:
type Emloyee struct {
ID int
Name, Address string
DoB time.Time
Position string
Salary int
ManagerID int
}
首字母大写的 struct field 是可以被外部访问的,小写则不能被外部访问。
type Point { X, Y int } type Circle struct { Point Radius int } type Wheel struct { Circle Spokes int } 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 neccessary here (and at Radius) } fmt.Printf("%#v\n", w) // Output: // Wheel{Circle:Circle{Point:Point{X:42, Y:8}, Radius:5}, Spokes:20}
# 副词使值按类似于 Go 语法的格式输出
如果 struct 中的所有 field 都是能够进行比较的,那么该 struct 就是能够进行比较的。我们使用 == 和 != 进行该 struct 类型的值或者表达式之间的比较:
type Point struct { X, Y int }
p := Point{1, 2}
q := Point{2, 1}
fmt.Println(p.X == q.X && p.Y == q.Y) // "false"
fmt.Println(p == q) // "false"
可比较的 struct 类型可以用作 map 的 key:
type address struct {
hostname string
port int
}
hits := make(map[address]int)
hits[address{"golang.org", 443}]++
Go 使用 struct embedding 机制使一个命名 struct 类型作为另一 struct 类型的 anonymous field,使得简单的 dot 表达式比如 x.f,可以表示 x.d.e.f。
type Point {
X, Y int
}
type Circle struct {
Center Point
Radius int
}
type Wheel struct {
Circle Circle
Spokes int
}
这样访问 Wheel 的 field 可能十分冗长,比如 Wheel{}.Circle.Center.X。
Go 允许我们声名一个 field 的 type 但不声名 name,这被称为 anonymous fields。field 的类型必须是一个命名类型或者是指向命名类型的指针。
type Circle struct {
Point
Radius int
}
type Wheel struct {
Circle
Spokes int
}
其使用方法如下:
var w Wheel
w.X = 8 // equivalent w.Circle.Point.X
w.Y = 8 // equivalent w.Circle.Point.Y
w.Radius = 5 // equivalent w.Circle.Radius
w.Spokes = 20
事实上,anonymous field 的名字是隐式声名的,它的名字就是它的命名类型名,这些名字在 dot 表达式中是可选的,可以显式使用,也可以不显式不使用。Circle 和 Point 都是首字母大写的,显然它们可以在声明它们的 package 之外被访问,但是如果是 circle 和 point 呢?在声明的 package 外,我们依然可以用 w.X = 8 进行访问,但是显式的使用 field name,w.circle.point.X,就不行了,因为 circle 和 point field 式不向外暴露的。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。