一 创建结构体变量和访问结构体字段

1 定义

a 方式1:直接声明

var person Person

b方式2:结构体类型{}

var person Person = Person{}

c 方式3:new (结构体类型)

var person *Person = new (Person)

d 方式4:&结构体类型{}

var person *Person = &Person{}

2 说明

a 第 3 种和第 4 种方式返回的是结构体指针。

b 结构体指针访问字段的标准方式是:(*结构体指针).字段名。比如: (*person).Name = "tom"。

c  go 做了一个简化,也支持结构体指针.字段名。比如:person.Name = "tom"。更加符合程序员使用的习惯,go 编译器底层对 person.Name 做了转化 (*person).Name。

3 代码

package main

import (
   "fmt"
)

type Person struct {
   Name string
   Age  int
}

func main() {
   // 方式2
   p2 := Person{"mary", 20}
   // p2.Name = "tom"
   // p2.Age = 18
   fmt.Println(p2)
   // 方式3
   var p3 *Person = new(Person)
   // 因为 p3 是一个指针,因此标准的给字段赋值方式 (*p3).Name = "smith" 也可以写成 p3.Name = "smith"
   // 原因: go 的设计者为了程序员使用方便,底层会对 p3.Name = "smith" 进行处理。会给 p3 加上取值运算 (*p3).Name = "smith"
   (*p3).Name = "smith"
   p3.Name = "john"
   (*p3).Age = 30
   p3.Age = 100
   fmt.Println(*p3)
   // 方式4
   // 下面的语句,也可以直接给字符赋值
   // var person *Person = &Person{"mary", 60}
   var person *Person = &Person{}
   // 因为 person 是一个指针,因此标准的访问字段的方法
   // (*person).Name = "scott"
   // go的设计者为了程序员使用方便,可以 person.Name = "scott"
   // 原因和上面一样,底层会对 person.Name = "scott" 进行处理, 会加上 (*person)
   (*person).Name = "scott"
   person.Name = "scott~~"
   (*person).Age = 88
   person.Age = 10
   fmt.Println(*person)
}

4 测试

{mary 20}

{john 100}

{scott~~ 10}

二 struct 类型的内存分配机制

1 小练习

a 代码

package main

import (
   "fmt"
)

type Person struct {
   Name string
   Age  int
}

func main() {
   var p1 Person
   p1.Age = 10
   p1.Name = "小明"

   var p2 Person = p1
   fmt.Println(p2.Age)
   p2.Name = "tom"
   fmt.Printf("p2.Name=%v p1.Name=%v",p2.Name,p1.Name)
}

b 测试

10

p2.Name=tom p1.Name=小明

c 图解

2 实战

a 代码

package main

import "fmt"

type Person struct {
   Name string
   Age  int
}

func main() {
   var p1 Person
   p1.Age = 10
   p1.Name = "小明"

   var p2 *Person = &p1 // 这里是关键
   fmt.Println((*p2).Age)
   fmt.Println(p2.Age)
   p2.Name = "tom~"
   fmt.Printf("p2.Name=%v p1.Name=%v \n", p2.Name, p1.Name)    // tom~ tom~
   fmt.Printf("p2.Name=%v p1.Name=%v \n", (*p2).Name, p1.Name) // tom~ tom~
   fmt.Printf("p1的地址%p\n", &p1)
   fmt.Printf("p2的地址%p p2的值%p\n", &p2, p2)
}

b 测试

10

10

p2.Name=tom~ p1.Name=tom~

p2.Name=tom~ p1.Name=tom~

p1的地址0xc04204c3a0

p2的地址0xc042070018 p2的值0xc04204c3a0

c 图解

3 代码分析