结构体
在Go语言中,结构体(struct)是一种聚合数据类型,可以将多个字段(属性)组合在一起,用于描述具有不同属性的数据对象。结构体类似于面向对象语言中的类,但它不支持继承和方法重载。
# 1. 定义和初始化结构体
# 1.1 定义结构体
结构体的定义使用关键字type
和struct
,格式为:
type Person struct {
Name string
Age int
City string
}
1
2
3
4
5
2
3
4
5
# 1.2 初始化结构体
可以通过多种方式初始化结构体。
// 使用字段名初始化
p1 := Person{Name: "Alice", Age: 25, City: "New York"}
fmt.Println(p1) // 输出: {Alice 25 New York}
// 按字段顺序初始化(不推荐)
p2 := Person{"Bob", 30, "Los Angeles"}
fmt.Println(p2) // 输出: {Bob 30 Los Angeles}
// 使用零值初始化
var p3 Person
fmt.Println(p3) // 输出: { 0 },未初始化的字段会使用类型的零值
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# 2. 结构体字段的访问和修改
结构体的字段可以通过.
操作符访问和修改。
p := Person{Name: "Charlie", Age: 28}
fmt.Println(p.Name) // 输出: Charlie
p.Age = 29 // 修改结构体字段的值
fmt.Println(p.Age) // 输出: 29
1
2
3
4
5
2
3
4
5
# 3. 结构体指针
Go支持使用指针来操作结构体,结构体指针允许直接修改原结构体的值。
p := Person{Name: "Diana", Age: 35}
pPtr := &p // 获取结构体的指针
pPtr.Age = 36 // 修改结构体字段值
fmt.Println(p.Age) // 输出: 36
1
2
3
4
2
3
4
在结构体指针上可以直接使用.
操作符来访问字段,而不需要显式解引用(*pPtr
)。
# 4. 结构体的嵌套
结构体可以包含另一个结构体作为字段,称为嵌套结构体。
type Address struct {
City string
Street string
}
type Person struct {
Name string
Age int
Address Address // 嵌套结构体
}
p := Person{Name: "Eve", Age: 40, Address: Address{City: "Seattle", Street: "Main St"}}
fmt.Println(p.Address.City) // 输出: Seattle
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
# 5. 结构体方法
在Go中,可以为结构体定义方法。方法是一个作用于特定类型实例的函数,方法接收器表示调用方法的具体实例。
type Person struct {
Name string
Age int
}
// 定义结构体方法
func (p Person) Greet() {
fmt.Printf("Hello, my name is %s and I am %d years old.\n", p.Name, p.Age)
}
func main() {
p := Person{Name: "Frank", Age: 32}
p.Greet() // 输出: Hello, my name is Frank and I am 32 years old.
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
# 5.1 指针接收器方法
使用指针接收器可以修改结构体的字段值。
func (p *Person) HaveBirthday() {
p.Age++
}
func main() {
p := Person{Name: "George", Age: 29}
p.HaveBirthday()
fmt.Println(p.Age) // 输出: 30
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 6. 匿名结构体
Go支持匿名结构体,即在定义和初始化时直接声明结构体而不定义类型名,适用于临时数据结构。
p := struct {
Name string
Age int
}{
Name: "Helen",
Age: 27,
}
fmt.Println(p) // 输出: {Helen 27}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 7. 结构体标签(Tag)
结构体标签是一种元信息,通常用于数据序列化(如JSON、XML)。标签写在结构体字段后面,使用反引号包裹。
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
}
func main() {
p := Person{Name: "Ivy", Age: 24}
data, _ := json.Marshal(p)
fmt.Println(string(data)) // 输出: {"name":"Ivy","age":24}
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# 8. 使用结构体的常见案例
# 8.1 JSON数据的序列化和反序列化
Go的encoding/json
包可以将结构体与JSON格式的数据互相转换。
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
}
func main() {
// 序列化
p := Person{Name: "John", Age: 35}
data, _ := json.Marshal(p)
fmt.Println(string(data)) // 输出: {"name":"John","age":35}
// 反序列化
jsonStr := `{"name":"Jane","age":29}`
var p2 Person
json.Unmarshal([]byte(jsonStr), &p2)
fmt.Println(p2) // 输出: {Jane 29}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 8.2 模拟数据库记录
结构体常用于模拟数据库中的记录。
type Employee struct {
ID int
Name string
Salary float64
}
func main() {
employees := []Employee{
{ID: 1, Name: "Alice", Salary: 50000},
{ID: 2, Name: "Bob", Salary: 60000},
}
for _, e := range employees {
fmt.Printf("ID: %d, Name: %s, Salary: %.2f\n", e.ID, e.Name, e.Salary)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 8.3 组织数据层次结构
结构体可以用来表达层次结构的数据,例如描述一家公司及其员工。
type Employee struct {
Name string
Age int
}
type Department struct {
Name string
Employees []Employee
}
func main() {
dept := Department{
Name: "Engineering",
Employees: []Employee{
{Name: "Alice", Age: 30},
{Name: "Bob", Age: 25},
},
}
fmt.Println(dept)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 总结
结构体是Go语言中非常重要的类型,用于表示具有多个属性的数据结构。掌握结构体的定义、初始化、嵌套、方法、标签等特性,可以帮助我们更高效地构建复杂的数据模型。
上次更新: 2024/11/21, 10:50:23