在 Go 中,struct是一系列具名元素,这些元素称为_字段_,每个字段都有一个名字和一个类型。字段名在 struct 内必须唯一。可以把 struct 和面向对象编程范式中的_类_做比较。
使用 type和struct关键字可以创建一个新的 struct,并显式定义各个字段的名字和类型。例如,下面定义了一个 Shape struct,它保存形状的名字和大小:
type Shape struct {
name string
size int
}
struct 中字段的命名遵循 Go 的约定:名字以小写字母开头的字段只对同一个包中的代码可见,而名字以大写字母开头的字段在其他包中也可见。
定义好 struct之后,就需要创建新的实例,用字段名给字段赋值,顺序随意:
s := Shape {
name: "Square",
size: 25,
}
要读取或修改实例的字段,可以使用 .表示法:
// Update the name and the size
s.name = "Circle"
s.size = 35
fmt.Printf("name: %s size: %d\n", s.name, s.size)
// Output: name: Circle size: 35
没有赋予初始值的字段,会得到它们的零值。例如:
s := Shape{name: "Circle"}
fmt.Printf("name: %s size: %d\n", s.name, s.size)
// Output: name: Circle size: 0
只要_按顺序_给出字段的值,也可以不使用字段名来创建 struct的实例:
s := Shape {
"Oval",
20,
}
不过,这种写法被认为是_脆弱的代码_,因为一旦新增字段就可能出问题,尤其是新字段的类型不同时。在下面的例子中,我们给 Shape增加了一个字段:
type Shape struct {
name string
description string // new field 'description' added
size int
}
s := Shape{
"Circle",
20,
}
// Since the second field of the struct is now a string and not an int,
// the compiler will throw an error when compiling the program:
// Output: cannot use 20 (type untyped int) as type string in field value
// Output: too few values in Shape{...}
有时,拥有一些帮助我们创建 struct 实例的函数会很有用。按照约定,这类函数通常叫 New,或者名字以 New开头;不过它们只是普通函数,你可以给它们取任何名字。它们可能会让你想起其他语言中的构造函数,但在 Go 中,它们只是普通函数。
在下面的例子中,用其中一个 New函数创建 Shape的新实例,并自动为形状的 size设置默认值:
func NewShape(name string) Shape {
return Shape{
name: name,
size: 100, //default-value for size is 100
}
}
NewShape("Triangle")
// => Shape { name: "Triangle", size: 100 }
使用 New函数有以下优点:
New函数通常与它们所初始化的 struct 声明在同一个包里,所以它们甚至可以初始化 struct 的私有字段想深入了解这种类型,可以看看这些资源:Go by Example: Structs、A Tour of Go: Structs 或 Structures in Go (structs)
new内置函数创建 struct 新实例的另一种方式是使用内置的 new:
s := new(Shape) // s will be of type *Shape (pointer to shape)
fmt.Printf("name: %s size: %d\n", s.name, s.size)
// Output: name: size: 0
在这个例子中,new创建了 struct Shape的一个实例,把所有值都初始化为各自类型的零值,并返回指向它的指针。
多数情况下,你不会看到用内置的 new创建 struct 新实例的写法。请优先使用 struct 字面量、自定义的 New函数,或者包中提供的其他能帮助你构建 struct 的函数。只有在万不得已时,才用内置的 new来创建 struct 的新实例。