go 结构体
结构体是复合类型(composite types),当需要定义一个类型,它由一系列属性组成,每个属性都有自己的类型和值的时候,就应该使用结构体,它把数据聚集在一起。然后可以访问这些数据,就好像它是一个独立实体的一部分。
定义
结构体定义的一般方式如下:
- type Identifier struct {
- field1 type1
- field2 type2
- ...
- }
赋值
结构体是值类型,因此可以通过 new 来创建。
我们可以使用 .
给字段赋值:
- structname.fieldname = value
同样的,也可以使用 .
获取结构体字段的值:
- structname.fieldname
在 Go 语言中这叫 selector。无论变量是一个 结构体类型
还是一个 结构体类型指针
,都使用同样的 selector-notation 来引用结构体的字段:
- type myStruct struct { i int }
- var v myStruct // v 是结构体类型变量
- var p *myStruct // p 是指向一个结构体类型变量的指针
- v.i
- p.i
下面来看一个例子
- // rectangle.go
- package rect
-
- type Rectangle struct {
- length int
- width int
- }
-
- func (r *Rectangle) Set(x,y int) {
- r.length = x
- r.width = y
- }
-
- func (r *Rectangle) Area() (res int) {
- res = r.length * r.width
- return
- }
-
- func (r *Rectangle) Perimeter() (res int) {
- res = (r.length + r.width) * 2
- return
- }
- // main.go
- package main
-
- import (
- "rect"
- "fmt"
- )
-
- func main() {
- rectangle := new(rect.Rectangle)
- rectangle.Set(1, 2)
- fmt.Println("rectangle is",rectangle)
- fmt.Println(rectangle.Area())
- fmt.Println(rectangle.Perimeter())
- }
运行结果
- rectangle is &{1 2}
- 2
- 6
注意:如果 XX 是一个结构体类型,那么表达式
new(XX)
和&XX{}
是等价的。
例如:
- type MyStruct struct {
- x int
- y int
- }
-
- my := new(MyStruct)
- my.x = 1
- my.y = 2
-
- 等价于
-
- my2 := &Mystrcut{1, 2}
工厂方法
你现在突然想,不能让别人看到我的结构体,我应该把它设为私有的,但是还想让别人使用我的结构体,该怎么办?
为了方便,通常会为类型定义一个工厂,按惯例,工厂的名字以 new 或 New 开头,它返回一个指向结构体实例的指针。形式如下:
- // mystruct.go
- package my
-
- type mystruct struct {
- ...
- }
-
- func NewMystruct() *mystruct {
- m : = new(mystruct) // 初始化 m
- return m
- }
在其他包里使用工厂方法:
- // main.go
- package main
-
- import "my"
- ...
-
- wrong : = new(my.mystruct) // 编译失败,mystruct 是私有的
- right : = my.NewMystruct() // 实例化 mystruct 的唯一方式