结构体

数组、切片和 Map 可以用来表示同一种数据类型的集合,但是当我们要表示不同数据类型的集合时就需要用到结构体。

结构体是由零个或多个任意类型的值聚合成的实体

关键字 typestruct 用来定义结构体:

  1. type StructName struct{
  2. FieldName type
  3. }

简单示例:定义一个学生结构体

  1. package main
  2. import "fmt"
  3. type Student struct {
  4. Age int
  5. Name string
  6. }
  7. func main() {
  8. stu := Student{
  9. Age: 18,
  10. Name: "name",
  11. }
  12. fmt.Println(stu)
  13. // 在赋值的时候,字段名可以忽略
  14. fmt.Println(Student{20, "new name"})
  15. return
  16. }

通常结构体中一个字段占一行,但是类型相同的字段,也可以放在同一行,例如:

  1. type Student struct{
  2. Age int
  3. Name, Address string
  4. }

一个结构体中的字段名是唯一的,例如一下代码,出现了两个 Name 字段,是错误的:

  1. type Student struct{
  2. Name string
  3. Name string
  4. }

结构体中的字段如果是小写字母开头,那么其他 package 就无法直接使用该字段,例如:

  1. // 在包 pk1 中定义 Student 结构体
  2. package pk1
  3. type Student struct{
  4. Age int
  5. name string
  6. }
  1. // 在另外一个包 pk2 中调用 Student 结构体
  2. package pk2
  3. func main(){
  4. stu := Student{}
  5. stu.Age = 18 //正确
  6. stu.name = "name" // 错误,因为`name` 字段为小写字母开头,不对外暴露
  7. }

结构体中可以内嵌结构体

但是需要注意的是:如果嵌入的结构体是本身,那么只能用指针。请看以下例子。

  1. package main
  2. import "fmt"
  3. type Tree struct {
  4. value int
  5. left, right *Tree
  6. }
  7. func main() {
  8. tree := Tree{
  9. value: 1,
  10. left: &Tree{
  11. value: 1,
  12. left: nil,
  13. right: nil,
  14. },
  15. right: &Tree{
  16. value: 2,
  17. left: nil,
  18. right: nil,
  19. },
  20. }
  21. fmt.Printf(">>> %#v\n", tree)
  22. }

结构体是可以比较的

前提是结构体中的字段类型是可以比较的

  1. package main
  2. import "fmt"
  3. type Tree struct {
  4. value int
  5. left, right *Tree
  6. }
  7. func main() {
  8. tree1 := Tree{
  9. value: 2,
  10. }
  11. tree2 := Tree{
  12. value: 1,
  13. }
  14. fmt.Printf(">>> %#v\n", tree1 == tree2)
  15. }

结构体内嵌匿名成员

声明一个成员对应的数据类型而不指名成员的名字;这类成员就叫匿名成员

  1. package main
  2. import "fmt"
  3. type Person struct {
  4. Age int
  5. Name string
  6. }
  7. type Student struct {
  8. Person
  9. }
  10. func main() {
  11. per := Person{
  12. Age: 18,
  13. Name: "name",
  14. }
  15. stu := Student{Person: per}
  16. fmt.Println("stu.Age: ", stu.Age)
  17. fmt.Println("stu.Name: ", stu.Name)
  18. }