结构体

什么是结构体?

结构体是一个复合类型,用于表示一组数据。

结构体由一系列属性组成,每个属性都有自己的类型和值。

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 博客
    }
}

results matching ""

    No results matching ""