Go 结构体:修订间差异
外观
Page creation by admin bot |
Page update by admin bot |
||
第1行: | 第1行: | ||
= Go结构体 = | = Go结构体 = | ||
''' | '''结构体(Struct)'''是Go语言中一种重要的复合数据类型,它允许开发者将不同类型的变量组合成一个逻辑单元。结构体是面向对象编程中"对象"的基础,用于表示现实世界中的实体及其属性。 | ||
== | == 基本概念 == | ||
结构体是由一系列'''字段(Fields)'''组成的集合,每个字段都有名称和类型。结构体定义了一个新的数据类型,可以用来创建该类型的变量(称为结构体实例)。 | |||
=== 定义结构体 === | |||
结构体使用<code>type</code>和<code>struct</code>关键字定义: | |||
<syntaxhighlight lang="go"> | <syntaxhighlight lang="go"> | ||
type Person struct { | type Person struct { | ||
Name | Name string | ||
Age | Age int | ||
City string | |||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
这个例子定义了一个<code>Person</code>结构体,包含三个字段:<code>Name</code>(字符串类型)、<code>Age</code>(整型)和<code>City</code>(字符串类型)。 | |||
== 创建和使用结构体 == | |||
=== | === 声明结构体变量 === | ||
结构体变量可以通过多种方式声明和初始化: | |||
<syntaxhighlight lang="go"> | <syntaxhighlight lang="go"> | ||
// 方式1:声明后分别赋值 | |||
var p1 Person | var p1 Person | ||
p1.Name = "Alice" | p1.Name = "Alice" | ||
p1.Age = 30 | p1.Age = 30 | ||
p1. | p1.City = "New York" | ||
= | // 方式2:使用结构体字面量 | ||
p2 := Person{"Bob", 25, "London"} | |||
// 方式3:使用字段名初始化 | |||
p3 := Person{ | |||
Name: | Name: "Charlie", | ||
Age: | Age: 35, | ||
City: "Paris", | |||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== | === 访问结构体字段 === | ||
使用点号(<code>.</code>)访问结构体字段: | |||
<syntaxhighlight lang="go"> | <syntaxhighlight lang="go"> | ||
fmt.Println(p1.Name) // 输出: Alice | |||
p2.Age = 26 // 修改字段值 | |||
</syntaxhighlight> | </syntaxhighlight> | ||
== | == 结构体的高级特性 == | ||
=== 匿名字段 === | |||
Go支持匿名字段,即没有显式名称的字段,其类型名即为字段名: | |||
<syntaxhighlight lang="go"> | <syntaxhighlight lang="go"> | ||
type Employee struct { | |||
Person // 匿名字段 | |||
Salary float64 | |||
} | |||
= | e := Employee{ | ||
Person: Person{"Dave", 40, "Berlin"}, | |||
Salary: 5000.0, | |||
} | |||
fmt.Println(e.Name) // 可以直接访问Person的字段 | |||
fmt.Println( | |||
</syntaxhighlight> | </syntaxhighlight> | ||
== 嵌套结构体 == | === 嵌套结构体 === | ||
结构体可以嵌套其他结构体: | 结构体可以嵌套其他结构体: | ||
第76行: | 第76行: | ||
type Address struct { | type Address struct { | ||
Street string | Street string | ||
ZipCode string | ZipCode string | ||
} | } | ||
type | type Company struct { | ||
Name string | Name string | ||
Address Address // 嵌套结构体 | Address Address // 嵌套结构体 | ||
} | } | ||
</syntaxhighlight> | |||
=== 结构体比较 === | |||
如果结构体的所有字段都是可比较的,那么结构体本身也是可比较的: | |||
<syntaxhighlight lang="go"> | |||
p1 := Person{"Alice", 30, "NY"} | |||
p2 := Person{"Alice", 30, "NY"} | |||
fmt.Println(p1 == p2) // 输出: true | |||
</syntaxhighlight> | </syntaxhighlight> | ||
== | == 结构体方法 == | ||
Go中可以为结构体定义'''方法''',这是Go实现面向对象编程的方式之一: | |||
<syntaxhighlight lang="go"> | <syntaxhighlight lang="go"> | ||
第109行: | 第106行: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
方法接收者可以是值类型或指针类型,后者允许修改结构体内容: | |||
<syntaxhighlight lang="go"> | <syntaxhighlight lang="go"> | ||
第119行: | 第114行: | ||
p1.Birthday() | p1.Birthday() | ||
fmt.Println(p1.Age) // | fmt.Println(p1.Age) // 年龄增加1 | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== 实际应用案例 == | == 实际应用案例 == | ||
=== | === 数据库记录表示 === | ||
结构体非常适合表示数据库表中的记录: | |||
<syntaxhighlight lang="go"> | <syntaxhighlight lang="go"> | ||
type | type Product struct { | ||
ID | ID int | ||
Name string | |||
Price float64 | |||
InStock bool | |||
} | } | ||
// 从数据库查询返回的产品 | |||
currentProduct := Product{ | |||
ID: 1001, | |||
Name: "Laptop", | |||
Price: 999.99, | |||
InStock: true, | |||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== | === JSON处理 === | ||
结构体与JSON之间的转换非常方便: | |||
<syntaxhighlight lang="go"> | <syntaxhighlight lang="go"> | ||
type | type User struct { | ||
Username string `json:"username"` | |||
Email string `json:"email"` | |||
} | } | ||
// JSON到结构体 | |||
jsonStr := `{"username":"alice","email":"alice@example.com"}` | |||
var user User | |||
// | json.Unmarshal([]byte(jsonStr), &user) | ||
// 结构体到JSON | |||
newJson, _ := json.Marshal(user) | |||
</syntaxhighlight> | </syntaxhighlight> | ||
== 性能考虑 == | == 性能考虑 == | ||
* 对于大型结构体,传递指针比传递值更高效 | |||
* | * 结构体字段的内存布局会影响缓存性能(考虑字段排列顺序) | ||
* | * 使用<code>struct{}</code>作为空结构体可以节省内存(常用于信号传递) | ||
== 结构体内存布局 == | |||
结构体在内存中是连续存储的,字段按照定义的顺序排列: | |||
<mermaid> | <mermaid> | ||
graph LR | |||
A[结构体起始地址] --> B[字段1] | |||
B --> C[字段2] | |||
C --> D[...] | |||
D --> E[字段N] | |||
</mermaid> | </mermaid> | ||
内存对齐规则: | |||
* 字段偏移量通常是其大小和对齐要求的倍数 | |||
* 编译器可能会插入填充字节以满足对齐要求 | |||
=== | == 总结 == | ||
Go结构体是构建复杂数据类型的基石,具有以下特点: | |||
* 组合而非继承的设计哲学 | |||
* 灵活的内存布局控制 | |||
* 与接口协同实现多态 | |||
* 高效的数据封装能力 | |||
掌握结构体是成为熟练Go开发者的关键一步,它在系统编程、Web开发和分布式系统等领域都有广泛应用。 | |||
[[Category:编程语言]] | [[Category:编程语言]] | ||
[[Category:Go]] | [[Category:Go]] | ||
[[Category:Go | [[Category:Go 数据结构]] |
2025年4月29日 (二) 04:38的最新版本
Go结构体[编辑 | 编辑源代码]
结构体(Struct)是Go语言中一种重要的复合数据类型,它允许开发者将不同类型的变量组合成一个逻辑单元。结构体是面向对象编程中"对象"的基础,用于表示现实世界中的实体及其属性。
基本概念[编辑 | 编辑源代码]
结构体是由一系列字段(Fields)组成的集合,每个字段都有名称和类型。结构体定义了一个新的数据类型,可以用来创建该类型的变量(称为结构体实例)。
定义结构体[编辑 | 编辑源代码]
结构体使用type
和struct
关键字定义:
type Person struct {
Name string
Age int
City string
}
这个例子定义了一个Person
结构体,包含三个字段:Name
(字符串类型)、Age
(整型)和City
(字符串类型)。
创建和使用结构体[编辑 | 编辑源代码]
声明结构体变量[编辑 | 编辑源代码]
结构体变量可以通过多种方式声明和初始化:
// 方式1:声明后分别赋值
var p1 Person
p1.Name = "Alice"
p1.Age = 30
p1.City = "New York"
// 方式2:使用结构体字面量
p2 := Person{"Bob", 25, "London"}
// 方式3:使用字段名初始化
p3 := Person{
Name: "Charlie",
Age: 35,
City: "Paris",
}
访问结构体字段[编辑 | 编辑源代码]
使用点号(.
)访问结构体字段:
fmt.Println(p1.Name) // 输出: Alice
p2.Age = 26 // 修改字段值
结构体的高级特性[编辑 | 编辑源代码]
匿名字段[编辑 | 编辑源代码]
Go支持匿名字段,即没有显式名称的字段,其类型名即为字段名:
type Employee struct {
Person // 匿名字段
Salary float64
}
e := Employee{
Person: Person{"Dave", 40, "Berlin"},
Salary: 5000.0,
}
fmt.Println(e.Name) // 可以直接访问Person的字段
嵌套结构体[编辑 | 编辑源代码]
结构体可以嵌套其他结构体:
type Address struct {
Street string
ZipCode string
}
type Company struct {
Name string
Address Address // 嵌套结构体
}
结构体比较[编辑 | 编辑源代码]
如果结构体的所有字段都是可比较的,那么结构体本身也是可比较的:
p1 := Person{"Alice", 30, "NY"}
p2 := Person{"Alice", 30, "NY"}
fmt.Println(p1 == p2) // 输出: true
结构体方法[编辑 | 编辑源代码]
Go中可以为结构体定义方法,这是Go实现面向对象编程的方式之一:
func (p Person) Greet() string {
return fmt.Sprintf("Hello, my name is %s and I'm %d years old.", p.Name, p.Age)
}
fmt.Println(p1.Greet()) // 调用方法
方法接收者可以是值类型或指针类型,后者允许修改结构体内容:
func (p *Person) Birthday() {
p.Age++
}
p1.Birthday()
fmt.Println(p1.Age) // 年龄增加1
实际应用案例[编辑 | 编辑源代码]
数据库记录表示[编辑 | 编辑源代码]
结构体非常适合表示数据库表中的记录:
type Product struct {
ID int
Name string
Price float64
InStock bool
}
// 从数据库查询返回的产品
currentProduct := Product{
ID: 1001,
Name: "Laptop",
Price: 999.99,
InStock: true,
}
JSON处理[编辑 | 编辑源代码]
结构体与JSON之间的转换非常方便:
type User struct {
Username string `json:"username"`
Email string `json:"email"`
}
// JSON到结构体
jsonStr := `{"username":"alice","email":"alice@example.com"}`
var user User
json.Unmarshal([]byte(jsonStr), &user)
// 结构体到JSON
newJson, _ := json.Marshal(user)
性能考虑[编辑 | 编辑源代码]
- 对于大型结构体,传递指针比传递值更高效
- 结构体字段的内存布局会影响缓存性能(考虑字段排列顺序)
- 使用
struct{}
作为空结构体可以节省内存(常用于信号传递)
结构体内存布局[编辑 | 编辑源代码]
结构体在内存中是连续存储的,字段按照定义的顺序排列:
内存对齐规则:
- 字段偏移量通常是其大小和对齐要求的倍数
- 编译器可能会插入填充字节以满足对齐要求
总结[编辑 | 编辑源代码]
Go结构体是构建复杂数据类型的基石,具有以下特点:
- 组合而非继承的设计哲学
- 灵活的内存布局控制
- 与接口协同实现多态
- 高效的数据封装能力
掌握结构体是成为熟练Go开发者的关键一步,它在系统编程、Web开发和分布式系统等领域都有广泛应用。