/* 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. 字段对齐:了解内存对齐规则 */