一 结构体的基本使用
结构体可以用来声明新的类型,作为其他类型的属性/字段的容器,如下定义一个学生结构体:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| type Person struct { name string age int }
var p1 Person = Person{"lisi", 20}
p2 := Person{age:30}
p3 := new(Person) p3.name = "zs" p3.age = 27
var p4 Person p4.name = "ww" p4.age = 30
|
贴士:
- struct的结构中的类型可以是任意类型,且存储空间是连续的,其字段按照声明时的顺序存放
- 如果结构体的所有的成员都是可以比较的,那么结构体本身也是可以比较的,使用 == != ,不支持 > 和 <
- 如果结构体的成员要被包外调用,需要大写首字母。
二 结构体地址与实例化
前面说过,对结构体的new其实是生成了一个指针类型。其实对结构体进行&
取地址操作时,也可以视为对该类型进行一次new
的实例化操作。
1 2 3 4
| ins := &T{}
# T是结构体类型 # ins为结构体的实例,类型为*T,是指针类型
|
四 内嵌结构体
当前结构体可以直接访问其内嵌结构体的内部字段:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| package main
import "fmt"
type Animal struct { Age int }
type Person struct { Animal Name string }
type Student struct { Person ClassName string }
func main() {
s1 := Student{ Person{ Animal: Animal { Age: 15, }, Name:"lisi", }, "一班", } fmt.Println(s1.Age) fmt.Println(s1.Person.Name)
var s2 Student s2.Name = "zs" s2.Age = 30 s2.ClassName = "二班" fmt.Println(s2.Age) fmt.Println(s2.Person.Name) }
|
四 匿名字段
结构体的字段名与类型一一对应,如果不提供名字,则为匿名字段。
匿名字段如果是一个struct,这个struct拥有的全部字段都被隐式引入了当前的struct。
1 2 3 4 5 6 7 8 9
| type Person struct { name string age int } type Student struct { Person classroom string }
|
不仅仅是struct,其他所有内置类型和自定义类型都可以作为匿名字段:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| package main
import "fmt" type Person struct { name string age int }
type course []string
type Student struct { Person course classroom string }
func main() {
s := Student{Person:Person{"LiLei", 17}, classroom:"二班"}
fmt.Println("name = ", s.name) fmt.Println("classroom = ", s.classroom)
s.course = []string{"语文", "美术"} fmt.Println("course = ", s.course) }
|
贴士:如果Person和Student中都有同一个字段,那么Go会优先访问当前层。例如二者都有tel
字段,那么s.tel
将会访问的是Student中的数据。