结构体
什么是结构体?
结构体是一个复合类型,用于表示一组数据。
结构体由一系列属性组成,每个属性都有自己的类型和值。
1. 内存管理
type Person struct {
name string
age int
}
// 初始化结构体
p1 := Person{"武沛齐", 18}
fmt.Println(p1.name, p1.age)
// 初始化结构体指针
p2 := &Person{"武沛齐", 1}
fmt.Println(p2.name, p2.age
2. 赋值
2.1. 赋值拷贝
type Person struct {
name string
age int
}
p1 := Person{name: "武沛齐", age: 18}
p2 := p1 // 内部将p1重新拷贝一份
fmt.Println(p1) // {武沛齐 18}
fmt.Println(p2) // {武沛齐 18}
p1.name = "alex"
fmt.Println(p1) // {alex 19}
fmt.Println(p2) // {武沛齐 19
2.2. 结构体指针赋值
type Person struct {
name string
age int
}
p1 := &Person{"武沛齐", 18}
p2 := p1
fmt.Println(p1) // &{武沛齐 18}
fmt.Println(p2) // &{武沛齐 18}
p1.name = "alex"
fmt.Println(p1) // &{alex 18}
fmt.Println(p2) // &{alex 18
基于结合结构体和结构体指针的特性,基于指针实现数据变化后同步遍布。
type Person struct {
name string
age int
}
p1 := Person{name: "二狗子", age: 19}
p2 := &p1
fmt.Println(p1) // {二狗子 19}
fmt.Println(p2) // &{二狗子 19}
p1.name = "alex"
fmt.Println(p1) // {alex 19}
fmt.Println(p2) // &{alex 19
2.3. 嵌套赋值拷贝
在存在结构体嵌套时,赋值会拷贝一份所有的数据。
type Address struct {
city, state string
}
type Person struct {
name string
age int
address Address
}
p1 := Person{name:"二狗子",age:19,address: Address{"北京", "BJ"}}
p2 := p1
fmt.Println(p1.address) // {"北京" "BJ"}
fmt.Println(p2.address) // {"北京" "BJ"}
p1.address.city = "上海"
fmt.Println(p1.address) // {"上海" "BJ"}
fmt.Println(p2.address) // {"北京" "BJ"}
2.4. 谁不拷贝?
其实本质上都拷贝了,只不过由于数据存储方式的不同,导致拷贝的有些是数据,有些是内存地址(指针)。
- 感觉拷贝:字符串、数组、整型等。
- 感觉不拷贝:map、切片。
package main
import "fmt"
func main() {
type Person struct {
name string
age int
hobby [2]string
num []int
parent map[string]string
}
p1 := Person{
name: "二狗子",
age: 19,
hobby: [2]string{"裸奔", "大保健"}, // 拷贝
num: []int{69, 19, 99, 38}, // 未拷贝 (内部维护指针指向数据存储的地方)
parent: map[string]string{"father": "Alex", "mother": "Monika"}, // 未拷贝 (内部维护指针指向数据存储的地方)
}
p2 := p1
fmt.Println(p1)
fmt.Println(p2)
p1.parent["father"] = "武沛齐"
fmt.Println(p1)
fmt.Println(p2)
}
注意:对于那些默认拷贝的情况,可以改变为指针类型,让数据实现同步修改。
type Address struct {
city, state string
}
type Person struct {
name string
age int
hobby *[2]string
num []int
parent map[string]string
address Address
}
p1 := Person{
name: "二狗子",
age: 19,
hobby: &[2]string{"裸奔", "大保健"},
num: []int{69, 19, 99, 38},
parent: map[string]string{"father": "Alex", "mother": "Monika"},
}
p2 := p1
p1.hobby[0] = "洗澡"
fmt.Println(p1.hobby) // &[洗澡 大保健]
fmt.Println(p2.hobby) // &[洗澡 大保健]
3. 结构体标签
package main
import (
"fmt"
"reflect"
)
func main() {
type Person struct {
name string "姓名"
age int32 "年龄"
blog string "博客"
}
p1 := Person{name: "武沛齐", age: 18, blog: "https://www.pythonav.com"}
p1Type := reflect.TypeOf(p1)
// 方式1
filed1 := p1Type.Field(0)
fmt.Println(filed1.Tag) // 姓名 filed1.Name -> name
// 方式2
filed2, _ := p1Type.FieldByName("blog")
fmt.Println(filed2.Tag) //
// 循环获取
fieldNum := p1Type.NumField() // 总共有多少个字段 3
// 循环:0 1 2
for index := 0; index < fieldNum; index++ {
field := p1Type.Field(index)
fmt.Println(field.Name, field.Tag) // name 姓名; age 年龄 ; blog 博客
}
}