我们可以使用切片来保存一组数据。
使用映射来保存一组键值。
但是这两种都只能保存一种类型,如果需要保存一种以上类型的数据,如保存学生的基本信息,包括学生的年龄(string 类型)和成绩(float 类型)等,就需要用到 struct

定义 struct

var myStruct struct {
	number float64
	word   string
	toggle bool
}
fmt.Printf("%#v\n", myStruct)
// 输入如下:
//struct { number float64; word string; toggle bool }{number:0, word:"", toggle:false}

当我们调用 Printf 中的%#v 的时候,它将 myStruct 中的值作为 struct 字面量打印。

使用点运算符对 struct 进行赋值和检索

myStruct.number = 3.14
myStruct.word = "Hello"
myStruct.toggle = true

fmt.Println(myStruct.number, myStruct.word, myStruct.toggle)

定义 struct 类型

可以使用 type 关键字定义 struct 类型。

type car struct {
	// fields
	name     string
	topSpeed float64
}

func main() {
	byd := car{}
	byd.name = "宋"
	byd.topSpeed = 220
	fmt.Println(byd)
	changCheng := car{
		name:     "哈佛H6",
		topSpeed: 200,
	}
	fmt.Println(changCheng)
}
}
// 输出
{宋 220}
{哈佛H5 200}

就像变量,类型定义可以被放在一个函数中。但是把它的作用域限定在该函数块中,意味着你不能在函数外面使用。所以类型经常定义在函数外的包级别。

使用函数修改 struct

Go 是一个按值传递的语言,意味着函数调用时接收的是一个参数的拷贝。

如果函数修改了参数值,它修改的只是拷贝,而不是原始值。

type Person struct {
	name string
	age  int
}

func changeName(p Person) {
	p.name = "Tom"
}
func main() {
	person := Person{
		name: "Jack",
		age:  18,
	}
	changeName(person)
	fmt.Println(person)  // {Jack 18}
}

解决方案是修改函数,使它能够接收一个值的指针来代替直接接收值。
当调用这个函数时,我们使用取址运算符(&)来传送我们需要更新的值的指针。然后在函数内部,我们使用*来更新指针指向的值。

我们可以使用指针来让函数也能更新 struct。

type Person struct {
	name string
	age  int
}

func changeName(p *Person) {
	p.name = "Tom"
}
func main() {
	person := Person{
		name: "Jack",
		age:  18,
	}
	changeName(&person)
	fmt.Println(person)  //{Tom 18}

}

通过指针访问 struct 的字段

我们可以使用*运算符(就像我们调用取值运算符)来获取指针指向的值。
但是当我们需要对指向struct的指针直接使用*运算符, 是无法工作的。

type myStruct struct {
	myField int
}

func main() {
	var structVal myStruct
	structVal.myField = 5
	var point *myStruct = &structVal

	fmt.Println(point.myField)  // ok 输出:5
	// fmt.Println(*point.myField)
    // error: cannot indirect point.myField (variable of type int)
}

正确的使用方式是,添加一个括号:

fmt.Println((*point).myField)  // ok 输出:5 

由于添加括号比较麻烦,因此go 运行时会自动处理,不管是调用,或是赋值,都可以直接使用point.myField 即可

struct 字面量

匿名 struct 字段