Go基础之结构体

结构体

结构体是一种数据类型, 可以保存多个维度数据的类型, 类似于面向对象中的类

定义结构体

使用 typestruct 关键字定义结构体

1
2
3
4
5
type 结构体名 struct {
字段名 字段类型
字段名 字段类型
...
}

例如:

1
2
3
4
5
6
// 定义一个结构体
type person struct {
name string
age int
city string
}

结构体实例化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 方法一
var p1 person
p1.name = "Tom"
p1.age = 18
p1.city = "上海"
fmt.Printf("%T %+v \n", p1, p1)

// 方法二 键值对初始化
var p2 = person{
name: "Jerry",
age: 19,
city: "北京",
}
fmt.Printf("%T %+v \n", p2, p2)

// 方法三 值列表初始化
var p3 = person{
"Lucy",
20,
"深圳",
}
fmt.Printf("%T %+v \n", p3, p3)

使用构造函数初始化

1
2
3
4
5
6
7
8
9
10
11
// 结构体的构造函数
func newPerson(name string, age int, city string) person {
return person{
name: name,
age: age,
city: city,
}
}
// 方法四 自定义构造函数初始化
var p4 = newPerson("Jack", 21, "广州")
fmt.Printf("p4: %T %+v \n", p4, p4)

匿名结构体

多用于临时场景

1
2
3
4
5
6
7
8
9
10
var user struct{Name string; Age int}
user.Name = "悟空"
user.Age = 18
fmt.Printf("%#v\n", user)
// 这个是简写
var a = struct {
x int
y int
}{10, 20}
fmt.Printf("%#v\n", a)

方法和接收者

方法是有接收者的函数, 接收者指的是哪个类型的变量可以调用这个函数

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
package main

import "fmt"

// 定义结构体
type person struct {
name string
age int
city string
}

// 给结构体造个方法
func (p person) dream() {
fmt.Printf("%s的梦想是学好Go语言!\n", p.name)
}

// 结构体的构造函数
func newPerson(name string, age int, city string) person {
return person{
name: name,
age: age,
city: city,
}
}

func main() {
var p1 = newPerson("Jack", 21, "广州")
fmt.Printf("p1: %T %+v \n", p1, p1)
p1.dream()
}

结构体是值类型

指针接收者

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
42
43
44
package main

import "fmt"

// 定义结构体
type person struct {
name string
age int
city string
}

// 给结构体造个方法
// 与下方的方法保持一致使用指针接收者
func (p *person) dream() {
fmt.Printf("%s的梦想是学好Go语言!\n", p.name)
}

// 指针接收者
// 1. 需要修改结构体变量的值时使用指针接收者
// 2. 结构体本身比较大,拷贝的内存开销比较大时使用指针接收者
// 3. 保持一致性
func (p *person) newYear() {
p.age += 1
fmt.Printf("%s过年啦,涨了一岁!\n", p.name)
}

// 结构体的构造函数
func newPerson(name string, age int, city string) person {
return person{
name: name,
age: age,
city: city,
}
}

func main() {
// 构造函数初始化
var p1 = newPerson("Jack", 21, "广州")
fmt.Printf("p1: %T %+v \n", p1, p1)
p1.dream()
fmt.Println(p1.age)
p1.newYear()
fmt.Println(p1.age)
}

结构体嵌套与匿名嵌套

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 addr struct {
province string
city string
}

type student struct {
name string
addr // 匿名嵌套别的结构体, 就是用类型名作为名称
}

func main() {
var tom = student{
name: "Tom",
addr: addr{
province: "江苏",
city: "无锡",
},
}
// {name:Tom addr:{province:江苏 city:无锡}}
fmt.Printf("%+v\n", tom)
// 无锡
fmt.Println(tom.addr.city)
// 无锡 匿名字段可以省略
fmt.Println(tom.city)
}

结构体的继承

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
package main

import "fmt"

type animal struct {
name string
}

func (a animal) move() {
fmt.Printf("%s在动...\n", a.name)
}

type dog struct {
feet uint8
animal // 匿名字段继承animal
}

func (d dog) wang() {
fmt.Printf("%s有%d条腿: 汪汪汪~\n", d.name, d.feet)
}

func main() {
var d = dog{
feet: uint8(4),
animal: animal{
name: "汤姆",
},
}
d.wang()
d.move()
fmt.Printf("%T %#v %d \n", d.feet, d.feet, d.feet)
}

结构体字段的可见性

结构体中字段大写开头表示可公开访问,小写表示私有(仅在定义当前结构体的包中可访问)

json 序列化和反序列化

结构体中的字段首字母要大写!!!
反序列化时要传递指针

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
42
43
44
45
46
47
48
49
50
51
52
53
54
package main

import (
"encoding/json"
"fmt"
"os"
)

// 结构体标签(Tag)
// `key1:"value1" key2:"value2"`
// 不要在key和value之间添加空格。
type person struct {
Name string `json:"name"` // 通过指定tag实现json序列化该字段时的key
Age int `json:"age"`
}

func main() {
var p1 = person{
Name: "Tom",
Age: 19,
}
var b, err = json.Marshal(p1)
if err != nil {
fmt.Println("json marshal failed")
os.Exit(1)
}
var jsonString = string(b)
fmt.Println(jsonString)

// 反序列化
var jsonString1 = `{"name": "理想", "age": 19}`
var p2 person
// 传指针
var err2 = json.Unmarshal([]byte(jsonString1), &p2)
if err2 != nil {
fmt.Println("json unmarshal failed")
os.Exit(1)
}
fmt.Printf("%#v\n", p2)

// 切片
var s3 = make([]person, 0, 5)
var p3 = person{
Name: "大壮",
Age: 20,
}
s3 = append(s3, p3)
var b3, err3 = json.Marshal(s3)
if err3 != nil {
fmt.Println("json marshal failed")
os.Exit(1)
}
fmt.Println(string(b3))
}

学习资料

  1. https://www.bilibili.com/video/BV1fz4y1m7Pm/?p=49
  2. https://www.liwenzhou.com/posts/Go/10-struct/

我的环境

  • Mac
  • go1.19
  • GoLand