14.Go复合类型-结构体
6:结构体
现在有一个需求,要求存储学生的详细信息,例如,学生的学号,学生的姓名,年龄,家庭住址等。
按照之前篇章学习的存储方式,可以以如下的方式进行存储:
//学生信息的一般表示法
var id int
var name string
var sex byte
var age int
var addr string
通过定义变量的信息,进行存储。
但是这种方式,比较麻烦,并且不利于数据的管理。
6.0 结构体的基本定义
在GO语言中,我们可以通过结构体来存储以上类型的数据,结构体的定义如下:
type Student struct {
id int
name string
sex byte
age int
addr string
}
type 后面跟着的是结构体的名字Student, struct表示定义的是一个结构体。
大括号中是结构体的成员,注意在定义结构体成员时,不要加var.
通过以上的定义,大家能够感觉出,通过结构体来定义复杂的数据结构,非常清晰。
结构体定义完成后,可以进行初始化。
6.1 结构体初始化
“
顺序初始化,每个成员必须初始化
”
//顺序初始化,每个成员必须初始化
student := Student{1, "mike", 'm', 18, "bj"}
fmt.Println("student = ", student)
//执行:
student = {1 mike 109 18 bj}
注意:顺序初始化,每个成员必须初始化,在初始化时,值的顺序与结构体成员的顺序保持一致。
“
指定成员初始化,没有初始化的成员,自动赋值为0
”
//指定成员初始化,没有初始化的成员,自动赋值为0
s2 := Student{name: "mike", addr: "bg"}
fmt.Println("s2 = ", s2)
//执行:
s2 = {0 mike 0 0 bg}
结构体定义完成后,结构体成员的使用。
“
逐个定义结构体变量
”
var s Student
s.id = 1001
s.name = "zhangsan"
s.age = 18
s.addr = "北京"
s.sex = 'm'
fmt.Println(s)
//执行:
{1001 zhangsan 109 18 北京}
6.2 结构体比较与赋值
“
两个结构体可以使用 == 或 != 运算符进行比较,但不支持 > 或 <。
”
// 两个结构体可以使用 == 或 != 运算符进行比较,但不支持 > 或 <。
s1 := Student{1, "mike", 'm', 18, "bj"}
s2 := Student{1, "mike", 'm', 18, "bj"}
s3 := Student{2, "mike", 'm', 18, "bj"}
fmt.Println("s1 == s2", s1 == s2)
fmt.Println("s1 == s3", s1 == s3)
// 执行:
s1 == s2 true
s1 == s3 false
“
同类型的两个结构体变量可以相互赋值。
”
// 同类型的两个结构体变量可以相互赋值。
s3 := Student{2, "mike", 'm', 18, "bj"}
var tmp Student
tmp = s3
fmt.Println("tmp = ", tmp)
// 执行:
tmp = {2 mike 109 18 bj}
6.3 结构体数组
在上面,我们已经对结构体的定义,与基本使用有一定的了解了,下面有一个需求:
用结构体存储多个学生的信息。
可以使用上面讲解的,通过结构体定义多个结构体变量,也可以定义结构体数组来存储。
结构体数组定义如下所示:
type Student struct {
id int
name string
score float64
}
func main() {
// 结构体数组
students := []Student{
Student{101, "张三", 100},
Student{102, "李四", 100},
Student{103, "王五", 100},
}
for i := 0; i < len(students); i++ {
fmt.Println(students[i].id, "--", students[i].name, "--", students[i].score)
}
}
//执行如下;
101 -- 张三 -- 100
102 -- 李四 -- 100
103 -- 王五 -- 100
可以通过循环的方式,将结构体数组中的每一项进行输出。
练习1:计算以上学生成绩的总分
type Student struct {
id int
name string
score float64
}
func main() {
// 结构体数组
students := []Student{
Student{101, "张三", 100},
Student{102, "李四", 89},
Student{103, "王五", 98},
}
// 计算学生成绩的总分
var sum float64
for i := 0; i < len(students); i++ {
fmt.Println(students[i].id, "--", students[i].name, "--", students[i].score)
sum += students[i].score
}
fmt.Println("总分是:", sum)
}
// 执行
101 -- 张三 -- 100
102 -- 李四 -- 89
103 -- 王五 -- 98
总分是: 287
练习2:输出以上学生成绩中最高分
type Student struct {
id int
name string
score float64
}
func main() {
// 结构体数组
students := []Student{
Student{101, "张三", 100},
Student{102, "李四", 89},
Student{103, "王五", 98},
}
// 计算学生成绩的总分
var sum float64
// 计算学生成绩的最高分
var max = students[0].score
for i := 0; i < len(students); i++ {
fmt.Println(students[i].id, "--", students[i].name, "--", students[i].score)
// 计算总分
sum += students[i].score
// 计算最高分
if max < students[i].score {
max = students[i].score
}
}
fmt.Println("总分是:", sum)
fmt.Println("最高分是:", max)
}
//执行如下:
101 -- 张三 -- 100
102 -- 李四 -- 89
103 -- 王五 -- 98
总分是: 287
最高分是: 100
6.4 结构体作为函数参数
结构体也可以作为函数参数,进行传递,如下所示:
type Student struct {
id int
name string
sex byte
age int
addr string
}
func Test(stu Student) {
stu.id = 666
fmt.Println("stu: ", stu)
}
func main() {
s := Student{1, "mike", 'm', 18, "bj"}
Test(s)
fmt.Println("s=", s)
}
// 执行如下:
stu: {666 mike 109 18 bj}
s= {1 mike 109 18 bj}
结构体作为函数参数进行传递,是值传递。
练习:3个学生,计算其平均分
思路:
1:定义一个结构体如下:
type Student struct {
id int
name string
score float64
}
2:定义计算结构体数组中学生成绩平均分的方法
func Avg(stu [3]Student) float64 {
var sum float64
for i := 0; i < len(stu); i++ {
sum += stu[i].score
}
return sum / float64(len(stu))
}
3:定义一个结构体数组,并且添加学生信息,同时调用 Avg() 方法计算平均成绩
var avg float64
students := [3]Student{}
for i := 0; i < 3; i++ {
fmt.Printf("请输入第%d个学生的编号,姓名,成绩", i+1)
fmt.Scan(&students[i].id, &students[i].name, &students[i].score)
}
avg = Avg(students)
fmt.Println("平均成绩: ", avg)
执行如下:
请输入第1个学生的编号,姓名,成绩
1 张三 99
请输入第2个学生的编号,姓名,成绩
2 李四 85
请输入第3个学生的编号,姓名,成绩
3 王五 100
平均成绩: 94.66666666666667
练习:3个学生,每个学生3门课程,求其平均值
思路和上题是一样的,不同之处在于结构体中,定义了一个数组类型的成员,存储三门成绩
type Student struct {
id int
name string
score [3]float64 // 定义数组,记录3门课程的分数
avge float64 // 该学生三门课程的平均分
}
func Avg(stu [3]Student) [3]Student {
var sum float64
for i := 0; i < len(stu); i++ {
//计算该Student的三门课程平均分
sum = stu[i].score[0] + stu[i].score[1] + stu[i].score[2]
stu[i].avge = sum / 3
}
return stu
}
func main() {
students := [3]Student{}
for i := 0; i < 3; i++ {
fmt.Printf("请输入第%d个学生的编号,姓名,成绩1, 成绩2,成绩3", i+1)
fmt.Scan(&students[i].id, &students[i].name, &students[i].score[0], &students[i].score[1], &students[i].score[2])
}
// 计算平均分
stus := Avg(students)
fmt.Println(stus)
}
执行如下:
请输入第1个学生的编号,姓名,成绩1, 成绩2,成绩3
1 李四 65 88 76.9
请输入第2个学生的编号,姓名,成绩1, 成绩2,成绩3
2 张三 88.9 98.5 56
请输入第3个学生的编号,姓名,成绩1, 成绩2,成绩3
3 王五 44 33 66
[{1 李四 [65 88 76.9] 76.63333333333334} {2 张三 [88.9 98.5 56] 81.13333333333334} {3 王五 [44 33 66] 47.666666666666664}]