This commit is contained in:
2025-08-24 01:15:18 +08:00
parent e51feb1296
commit ec23aa5c26
6 changed files with 3631 additions and 3 deletions

View File

@@ -0,0 +1,892 @@
/*
04-structs.go - Go 语言结构体详解
学习目标:
1. 理解结构体的概念和作用
2. 掌握结构体的定义和使用
3. 学会结构体的初始化方式
4. 了解结构体的嵌入和组合
5. 掌握结构体的实际应用场景
知识点:
- 结构体的定义和特性
- 结构体的初始化方式
- 结构体字段的访问和修改
- 结构体的方法
- 结构体的嵌入和组合
- 结构体的标签
- 结构体的比较和拷贝
*/
package main
import (
"fmt"
)
func main() {
fmt.Println("=== Go 语言结构体详解 ===\n")
// 演示结构体的基本概念
demonstrateBasicStructs()
// 演示结构体的初始化
demonstrateStructInitialization()
// 演示结构体的方法
demonstrateStructMethods()
// 演示结构体的嵌入
demonstrateStructEmbedding()
// 演示结构体的标签
demonstrateStructTags()
// 演示结构体的高级特性
demonstrateAdvancedStructFeatures()
// 演示结构体的实际应用
demonstratePracticalApplications()
}
// demonstrateBasicStructs 演示结构体的基本概念
func demonstrateBasicStructs() {
fmt.Println("1. 结构体的基本概念:")
// 结构体的基本特性
fmt.Printf(" 结构体的基本特性:\n")
fmt.Printf(" - 用户自定义的复合数据类型\n")
fmt.Printf(" - 将相关数据组织在一起\n")
fmt.Printf(" - 值类型,赋值和传参会拷贝\n")
fmt.Printf(" - 可以有方法\n")
fmt.Printf(" - 支持嵌入和组合\n")
// 基本结构体示例
fmt.Printf(" 基本结构体示例:\n")
// 创建结构体实例
var p Person
fmt.Printf(" 零值结构体: %+v\n", p)
// 设置字段值
p.Name = "Alice"
p.Age = 25
p.Email = "alice@example.com"
fmt.Printf(" 设置字段后: %+v\n", p)
// 访问字段
fmt.Printf(" 姓名: %s\n", p.Name)
fmt.Printf(" 年龄: %d\n", p.Age)
fmt.Printf(" 邮箱: %s\n", p.Email)
// 结构体比较
fmt.Printf(" 结构体比较:\n")
p1 := Person{Name: "Bob", Age: 30, Email: "bob@example.com"}
p2 := Person{Name: "Bob", Age: 30, Email: "bob@example.com"}
p3 := Person{Name: "Charlie", Age: 25, Email: "charlie@example.com"}
fmt.Printf(" p1 == p2: %t\n", p1 == p2)
fmt.Printf(" p1 == p3: %t\n", p1 == p3)
// 结构体作为值类型
fmt.Printf(" 结构体作为值类型:\n")
original := Person{Name: "David", Age: 35, Email: "david@example.com"}
copied := original
fmt.Printf(" 原结构体: %+v\n", original)
fmt.Printf(" 拷贝结构体: %+v\n", copied)
// 修改拷贝不影响原结构体
copied.Age = 40
fmt.Printf(" 修改拷贝后:\n")
fmt.Printf(" 原结构体: %+v\n", original)
fmt.Printf(" 拷贝结构体: %+v\n", copied)
fmt.Println()
}
// demonstrateStructInitialization 演示结构体的初始化
func demonstrateStructInitialization() {
fmt.Println("2. 结构体的初始化:")
// 方式1: 零值初始化
fmt.Printf(" 方式1 - 零值初始化:\n")
var p1 Person
fmt.Printf(" var p1 Person: %+v\n", p1)
// 方式2: 字段名初始化
fmt.Printf(" 方式2 - 字段名初始化:\n")
p2 := Person{
Name: "Alice",
Age: 25,
Email: "alice@example.com",
}
fmt.Printf(" 字段名初始化: %+v\n", p2)
// 方式3: 位置初始化(不推荐)
fmt.Printf(" 方式3 - 位置初始化:\n")
p3 := Person{"Bob", 30, "bob@example.com"}
fmt.Printf(" 位置初始化: %+v\n", p3)
// 方式4: 部分初始化
fmt.Printf(" 方式4 - 部分初始化:\n")
p4 := Person{
Name: "Charlie",
Age: 35,
// Email 使用零值
}
fmt.Printf(" 部分初始化: %+v\n", p4)
// 方式5: 使用 new 函数
fmt.Printf(" 方式5 - 使用 new 函数:\n")
p5 := new(Person)
p5.Name = "David"
p5.Age = 40
fmt.Printf(" new(Person): %+v\n", *p5)
// 方式6: 结构体字面量的地址
fmt.Printf(" 方式6 - 结构体字面量的地址:\n")
p6 := &Person{
Name: "Eve",
Age: 28,
Email: "eve@example.com",
}
fmt.Printf(" &Person{...}: %+v\n", *p6)
// 复杂结构体初始化
fmt.Printf(" 复杂结构体初始化:\n")
addr := Address{
Street: "123 Main St",
City: "New York",
Country: "USA",
ZipCode: "10001",
}
employee := Employee{
Person: Person{
Name: "Frank",
Age: 32,
Email: "frank@company.com",
},
ID: 1001,
Position: "Software Engineer",
Salary: 75000,
Address: addr,
}
fmt.Printf(" 复杂结构体: %+v\n", employee)
// 匿名结构体
fmt.Printf(" 匿名结构体:\n")
point := struct {
X, Y int
}{
X: 10,
Y: 20,
}
fmt.Printf(" 匿名结构体: %+v\n", point)
fmt.Println()
}//
demonstrateStructMethods 演示结构体的方法
func demonstrateStructMethods() {
fmt.Println("3. 结构体的方法:")
// 创建结构体实例
fmt.Printf(" 结构体方法调用:\n")
rect := Rectangle{Width: 10, Height: 5}
fmt.Printf(" 矩形: %+v\n", rect)
fmt.Printf(" 面积: %.2f\n", rect.Area())
fmt.Printf(" 周长: %.2f\n", rect.Perimeter())
// 值接收者 vs 指针接收者
fmt.Printf(" 值接收者 vs 指针接收者:\n")
// 值接收者方法
fmt.Printf(" 调用值接收者方法:\n")
info := rect.String()
fmt.Printf(" String(): %s\n", info)
// 指针接收者方法
fmt.Printf(" 调用指针接收者方法:\n")
fmt.Printf(" 修改前: %+v\n", rect)
rect.Scale(2.0)
fmt.Printf(" Scale(2.0)后: %+v\n", rect)
// 方法链调用
fmt.Printf(" 方法链调用:\n")
rect2 := Rectangle{Width: 3, Height: 4}
fmt.Printf(" 原矩形: %+v\n", rect2)
result := rect2.SetWidth(6).SetHeight(8)
fmt.Printf(" 链式调用后: %+v\n", *result)
// 结构体方法作为函数值
fmt.Printf(" 结构体方法作为函数值:\n")
circle := Circle{Radius: 5}
areaFunc := circle.Area
circumferenceFunc := circle.Circumference
fmt.Printf(" 圆形: %+v\n", circle)
fmt.Printf(" 方法值调用 - 面积: %.2f\n", areaFunc())
fmt.Printf(" 方法值调用 - 周长: %.2f\n", circumferenceFunc())
fmt.Println()
}
// demonstrateStructEmbedding 演示结构体的嵌入
func demonstrateStructEmbedding() {
fmt.Println("4. 结构体的嵌入:")
// 具名嵌入
fmt.Printf(" 具名嵌入:\n")
emp := Employee{
Person: Person{
Name: "Alice",
Age: 30,
Email: "alice@company.com",
},
ID: 1001,
Position: "Manager",
Salary: 80000,
}
fmt.Printf(" 员工信息: %+v\n", emp)
fmt.Printf(" 访问嵌入字段: %s, %d\n", emp.Person.Name, emp.Person.Age)
// 匿名嵌入
fmt.Printf(" 匿名嵌入:\n")
manager := Manager{
Person: Person{
Name: "Bob",
Age: 35,
Email: "bob@company.com",
},
Department: "Engineering",
TeamSize: 10,
}
fmt.Printf(" 经理信息: %+v\n", manager)
// 直接访问嵌入字段
fmt.Printf(" 直接访问嵌入字段:\n")
fmt.Printf(" 姓名: %s\n", manager.Name) // 等同于 manager.Person.Name
fmt.Printf(" 年龄: %d\n", manager.Age) // 等同于 manager.Person.Age
fmt.Printf(" 邮箱: %s\n", manager.Email) // 等同于 manager.Person.Email
// 调用嵌入类型的方法
fmt.Printf(" 调用嵌入类型的方法:\n")
info := manager.GetInfo() // Person 的方法
fmt.Printf(" GetInfo(): %s\n", info)
// 方法重写
fmt.Printf(" 方法重写:\n")
student := Student{
Person: Person{
Name: "Charlie",
Age: 20,
Email: "charlie@university.edu",
},
StudentID: "S12345",
Major: "Computer Science",
GPA: 3.8,
}
fmt.Printf(" 学生信息: %+v\n", student)
// Student 重写了 GetInfo 方法
studentInfo := student.GetInfo()
fmt.Printf(" Student.GetInfo(): %s\n", studentInfo)
// 仍然可以访问原始方法
personInfo := student.Person.GetInfo()
fmt.Printf(" Person.GetInfo(): %s\n", personInfo)
// 多重嵌入
fmt.Printf(" 多重嵌入:\n")
contact := ContactInfo{
Phone: "123-456-7890",
Address: "123 Main St",
}
fullEmployee := FullEmployee{
Person: Person{Name: "David", Age: 28, Email: "david@company.com"},
Employee: Employee{ID: 1002, Position: "Developer", Salary: 70000},
ContactInfo: contact,
}
fmt.Printf(" 完整员工信息: %+v\n", fullEmployee)
fmt.Printf(" 访问各层字段:\n")
fmt.Printf(" 姓名: %s\n", fullEmployee.Person.Name)
fmt.Printf(" 职位: %s\n", fullEmployee.Employee.Position)
fmt.Printf(" 电话: %s\n", fullEmployee.ContactInfo.Phone)
fmt.Println()
}
// demonstrateStructTags 演示结构体的标签
func demonstrateStructTags() {
fmt.Println("5. 结构体的标签:")
fmt.Printf(" 结构体标签用于元数据,常用于序列化、验证等\n")
// 创建带标签的结构体实例
user := User{
ID: 1,
Username: "alice",
Email: "alice@example.com",
FullName: "Alice Smith",
IsActive: true,
CreatedAt: time.Now(),
}
fmt.Printf(" 用户信息: %+v\n", user)
// 使用反射读取标签
fmt.Printf(" 使用反射读取标签:\n")
userType := reflect.TypeOf(user)
for i := 0; i < userType.NumField(); i++ {
field := userType.Field(i)
jsonTag := field.Tag.Get("json")
dbTag := field.Tag.Get("db")
validateTag := field.Tag.Get("validate")
fmt.Printf(" 字段 %s:\n", field.Name)
if jsonTag != "" {
fmt.Printf(" json: %s\n", jsonTag)
}
if dbTag != "" {
fmt.Printf(" db: %s\n", dbTag)
}
if validateTag != "" {
fmt.Printf(" validate: %s\n", validateTag)
}
}
// 标签的实际应用
fmt.Printf(" 标签的实际应用:\n")
fmt.Printf(" - JSON 序列化/反序列化\n")
fmt.Printf(" - 数据库 ORM 映射\n")
fmt.Printf(" - 数据验证\n")
fmt.Printf(" - 配置文件解析\n")
fmt.Printf(" - API 文档生成\n")
fmt.Println()
}
// demonstrateAdvancedStructFeatures 演示结构体的高级特性
func demonstrateAdvancedStructFeatures() {
fmt.Println("6. 结构体的高级特性:")
// 结构体作为映射的值
fmt.Printf(" 结构体作为映射的值:\n")
users := map[string]Person{
"alice": {Name: "Alice", Age: 25, Email: "alice@example.com"},
"bob": {Name: "Bob", Age: 30, Email: "bob@example.com"},
}
fmt.Printf(" 用户映射: %+v\n", users)
// 结构体切片
fmt.Printf(" 结构体切片:\n")
people := []Person{
{Name: "Alice", Age: 25, Email: "alice@example.com"},
{Name: "Bob", Age: 30, Email: "bob@example.com"},
{Name: "Charlie", Age: 35, Email: "charlie@example.com"},
}
fmt.Printf(" 人员列表:\n")
for i, person := range people {
fmt.Printf(" %d: %s (%d岁)\n", i+1, person.Name, person.Age)
}
// 结构体指针切片
fmt.Printf(" 结构体指针切片:\n")
var personPtrs []*Person
for i := range people {
personPtrs = append(personPtrs, &people[i])
}
// 修改通过指针
personPtrs[0].Age = 26
fmt.Printf(" 修改后的第一个人: %+v\n", people[0])
// 空结构体
fmt.Printf(" 空结构体:\n")
type Empty struct{}
var empty Empty
fmt.Printf(" 空结构体大小: %d 字节\n", reflect.TypeOf(empty).Size())
fmt.Printf(" 空结构体常用于信号传递和集合实现\n")
// 使用空结构体实现集合
set := make(map[string]struct{})
set["item1"] = struct{}{}
set["item2"] = struct{}{}
fmt.Printf(" 集合: %v\n", getMapKeys(set))
// 结构体的内存对齐
fmt.Printf(" 结构体的内存对齐:\n")
type Aligned struct {
a bool // 1 byte
b int64 // 8 bytes
c bool // 1 byte
}
type Optimized struct {
b int64 // 8 bytes
a bool // 1 byte
c bool // 1 byte
}
fmt.Printf(" 未优化结构体大小: %d 字节\n", reflect.TypeOf(Aligned{}).Size())
fmt.Printf(" 优化后结构体大小: %d 字节\n", reflect.TypeOf(Optimized{}).Size())
fmt.Println()
}
// demonstratePracticalApplications 演示结构体的实际应用
func demonstratePracticalApplications() {
fmt.Println("7. 结构体的实际应用:")
// 应用1: 配置管理
fmt.Printf(" 应用1 - 配置管理:\n")
config := Config{
Server: ServerConfig{
Host: "localhost",
Port: 8080,
SSL: false,
},
Database: DatabaseConfig{
Host: "localhost",
Port: 5432,
Username: "admin",
Password: "secret",
Database: "myapp",
},
Cache: CacheConfig{
Enabled: true,
TTL: 300,
MaxSize: 1000,
},
}
fmt.Printf(" 应用配置: %+v\n", config)
fmt.Printf(" 服务器地址: %s:%d\n", config.Server.Host, config.Server.Port)
fmt.Printf(" 数据库连接: %s@%s:%d/%s\n",
config.Database.Username, config.Database.Host,
config.Database.Port, config.Database.Database)
// 应用2: HTTP 请求/响应
fmt.Printf(" 应用2 - HTTP 请求/响应:\n")
request := HTTPRequest{
Method: "POST",
URL: "/api/users",
Headers: map[string]string{
"Content-Type": "application/json",
"Authorization": "Bearer token123",
},
Body: `{"name": "Alice", "email": "alice@example.com"}`,
}
response := HTTPResponse{
StatusCode: 201,
Headers: map[string]string{
"Content-Type": "application/json",
},
Body: `{"id": 1, "name": "Alice", "email": "alice@example.com"}`,
}
fmt.Printf(" HTTP 请求: %+v\n", request)
fmt.Printf(" HTTP 响应: %+v\n", response)
// 应用3: 数据传输对象 (DTO)
fmt.Printf(" 应用3 - 数据传输对象:\n")
userDTO := UserDTO{
ID: 1,
Username: "alice",
Profile: ProfileDTO{
FirstName: "Alice",
LastName: "Smith",
Bio: "Software Developer",
},
Settings: SettingsDTO{
Theme: "dark",
Notifications: true,
Language: "en",
},
}
fmt.Printf(" 用户 DTO: %+v\n", userDTO)
// 应用4: 事件系统
fmt.Printf(" 应用4 - 事件系统:\n")
events := []Event{
{
ID: 1,
Type: "user.created",
Timestamp: time.Now(),
Data: map[string]interface{}{
"user_id": 123,
"email": "user@example.com",
},
},
{
ID: 2,
Type: "order.placed",
Timestamp: time.Now(),
Data: map[string]interface{}{
"order_id": 456,
"amount": 99.99,
},
},
}
fmt.Printf(" 事件列表:\n")
for _, event := range events {
fmt.Printf(" 事件 %d: %s (时间: %s)\n",
event.ID, event.Type, event.Timestamp.Format("15:04:05"))
fmt.Printf(" 数据: %+v\n", event.Data)
}
// 应用5: 状态机
fmt.Printf(" 应用5 - 状态机:\n")
fsm := StateMachine{
CurrentState: "idle",
States: map[string]State{
"idle": {
Name: "idle",
Transitions: map[string]string{
"start": "running",
},
},
"running": {
Name: "running",
Transitions: map[string]string{
"pause": "paused",
"stop": "idle",
},
},
"paused": {
Name: "paused",
Transitions: map[string]string{
"resume": "running",
"stop": "idle",
},
},
},
}
fmt.Printf(" 状态机当前状态: %s\n", fsm.CurrentState)
// 状态转换
if newState, ok := fsm.States[fsm.CurrentState].Transitions["start"]; ok {
fsm.CurrentState = newState
fmt.Printf(" 执行 'start' 转换后状态: %s\n", fsm.CurrentState)
}
fmt.Println()
}// ===
======= 结构体定义 ==========
// 基本结构体
type Person struct {
Name string
Age int
Email string
}
// Person 的方法
func (p Person) GetInfo() string {
return fmt.Sprintf("%s (%d岁) - %s", p.Name, p.Age, p.Email)
}
func (p Person) IsAdult() bool {
return p.Age >= 18
}
// 地址结构体
type Address struct {
Street string
City string
Country string
ZipCode string
}
// 员工结构体(具名嵌入)
type Employee struct {
Person Person // 具名嵌入
ID int
Position string
Salary float64
Address Address
}
// 几何图形结构体
type Rectangle struct {
Width float64
Height float64
}
// Rectangle 的方法
func (r Rectangle) Area() float64 {
return r.Width * r.Height
}
func (r Rectangle) Perimeter() float64 {
return 2 * (r.Width + r.Height)
}
func (r Rectangle) String() string {
return fmt.Sprintf("Rectangle(%.1f x %.1f)", r.Width, r.Height)
}
// 指针接收者方法
func (r *Rectangle) Scale(factor float64) {
r.Width *= factor
r.Height *= factor
}
// 方法链
func (r *Rectangle) SetWidth(width float64) *Rectangle {
r.Width = width
return r
}
func (r *Rectangle) SetHeight(height float64) *Rectangle {
r.Height = height
return r
}
// 圆形结构体
type Circle struct {
Radius float64
}
func (c Circle) Area() float64 {
return 3.14159 * c.Radius * c.Radius
}
func (c Circle) Circumference() float64 {
return 2 * 3.14159 * c.Radius
}
// 经理结构体(匿名嵌入)
type Manager struct {
Person // 匿名嵌入
Department string
TeamSize int
}
// 学生结构体(方法重写)
type Student struct {
Person
StudentID string
Major string
GPA float64
}
// 重写 Person 的 GetInfo 方法
func (s Student) GetInfo() string {
return fmt.Sprintf("学生 %s (%d岁) - %s专业, 学号: %s, GPA: %.1f",
s.Name, s.Age, s.Major, s.StudentID, s.GPA)
}
// 联系信息结构体
type ContactInfo struct {
Phone string
Address string
}
// 完整员工结构体(多重嵌入)
type FullEmployee struct {
Person
Employee
ContactInfo
}
// 带标签的结构体
type User struct {
ID int `json:"id" db:"id" validate:"required"`
Username string `json:"username" db:"username" validate:"required,min=3,max=20"`
Email string `json:"email" db:"email" validate:"required,email"`
FullName string `json:"full_name" db:"full_name"`
IsActive bool `json:"is_active" db:"is_active"`
CreatedAt time.Time `json:"created_at" db:"created_at"`
}
// 配置结构体
type Config struct {
Server ServerConfig
Database DatabaseConfig
Cache CacheConfig
}
type ServerConfig struct {
Host string
Port int
SSL bool
}
type DatabaseConfig struct {
Host string
Port int
Username string
Password string
Database string
}
type CacheConfig struct {
Enabled bool
TTL int
MaxSize int
}
// HTTP 请求/响应结构体
type HTTPRequest struct {
Method string
URL string
Headers map[string]string
Body string
}
type HTTPResponse struct {
StatusCode int
Headers map[string]string
Body string
}
// 数据传输对象
type UserDTO struct {
ID int `json:"id"`
Username string `json:"username"`
Profile ProfileDTO `json:"profile"`
Settings SettingsDTO `json:"settings"`
}
type ProfileDTO struct {
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
Bio string `json:"bio"`
}
type SettingsDTO struct {
Theme string `json:"theme"`
Notifications bool `json:"notifications"`
Language string `json:"language"`
}
// 事件结构体
type Event struct {
ID int `json:"id"`
Type string `json:"type"`
Timestamp time.Time `json:"timestamp"`
Data map[string]interface{} `json:"data"`
}
// 状态机结构体
type StateMachine struct {
CurrentState string
States map[string]State
}
type State struct {
Name string
Transitions map[string]string
}
// ========== 辅助函数 ==========
// 获取映射的键
func getMapKeys(m map[string]struct{}) []string {
var keys []string
for key := range m {
keys = append(keys, key)
}
return keys
}
/*
运行这个程序:
go run 04-structs.go
学习要点:
1. 结构体是用户自定义的复合数据类型
2. 结构体是值类型,赋值和传参会拷贝整个结构体
3. 结构体可以有方法,支持面向对象编程
4. 结构体支持嵌入和组合,实现代码复用
5. 结构体标签用于元数据,常用于序列化和验证
结构体的特性:
1. 类型安全:编译时检查字段类型
2. 内存效率:字段在内存中连续存储
3. 可比较性:所有字段可比较时结构体可比较
4. 零值:所有字段都为零值的结构体
5. 方法:可以定义方法操作结构体
初始化方式:
1. 零值初始化var s Struct
2. 字段名初始化Struct{Field: value}
3. 位置初始化Struct{value1, value2}
4. 部分初始化Struct{Field1: value}
5. 指针初始化:&Struct{} 或 new(Struct)
结构体嵌入:
1. 具名嵌入:显式字段名
2. 匿名嵌入:直接访问嵌入字段
3. 方法继承:自动获得嵌入类型的方法
4. 方法重写:可以重写嵌入类型的方法
结构体标签:
1. 元数据:为字段提供额外信息
2. 反射访问:通过反射读取标签
3. 常见用途JSON、数据库、验证
4. 格式:`key:"value" key2:"value2"`
最佳实践:
1. 字段名使用驼峰命名
2. 导出字段首字母大写
3. 合理组织字段顺序(内存对齐)
4. 使用指针接收者修改结构体
5. 适当使用嵌入实现代码复用
常见应用场景:
1. 数据模型和实体
2. 配置管理
3. API 请求/响应
4. 事件和消息
5. 状态管理
6. 数据传输对象
注意事项:
1. 结构体是值类型,大结构体传参考虑性能
2. 嵌入字段的方法可能被重写
3. 结构体比较要求所有字段可比较
4. 注意内存对齐对结构体大小的影响
5. 合理使用标签,避免过度复杂化
内存优化:
1. 字段排序:大字段在前,小字段在后
2. 使用指针:大结构体考虑使用指针
3. 空结构体:零内存占用,适合信号传递
4. 字段对齐:了解内存对齐规则
*/