2.5 【数据结构】Go语言的结构体
结构体 (Struct)
什么是结构体
体是一种自定义的数据类型,用于将不同类型的数据组合在一起。它类似于其他语言中的类,但更简单
结构体的定义和初始化
1. 定义结构体
type Person struct {
Name string
Age int
City string
}
2. 创建结构体实例
// 方法 1:按字段顺序初始化
person1 := Person{"张三", 25, "北京"}
// 方法 2:指定字段名初始化
person2 := Person{
Name: "李四",
Age: 30,
City: "上海",
}
// 方法 3:零值初始化后赋值
var person3 Person
person3.Name = "王五"
person3.Age = 28
person3.City = "广州"
// 方法 4:使用 new 函数
person4 := new(Person)
person4.Name = "赵六"
结构体的基本操作
1. 访问和修改字段
person := Person{Name: "张三", Age: 25, City: "北京"}
fmt.Println(person.Name) // 访问字段
person.Age = 26 // 修改字段
2. 结构体指针
person := &Person{Name: "张三", Age: 25, City: "北京"}
fmt.Println(person.Name) // Go 自动解引用
(*person).Age = 26 // 显式解引用
3. 匿名字段
type Employee struct {
Person // 匿名字段(嵌入)
ID int
Salary float64
}
emp := Employee{
Person: Person{Name: "张三", Age: 25, City: "北京"},
ID: 1001,
Salary: 8000.0,
}
fmt.Println(emp.Name) // 可以直接访问嵌入字段
结构体方法
1. 值接收器方法
func (p Person) GetInfo() string {
return fmt.Sprintf("姓名: %s, 年龄: %d, 城市: %s", p.Name, p.Age, p.City)
}
2. 指针接收器方法
func (p *Person) SetAge(age int) {
p.Age = age
}
func (p *Person) HaveBirthday() {
p.Age++
}
结构体标签
结构体标签常用于 JSON 序列化、数据验证等场景:
type User struct {
ID int `json:"id" db:"user_id"`
Username string `json:"username" db:"username"`
Email string `json:"email" db:"email"`
Password string `json:"-" db:"password"` // JSON 中忽略此字段
}
实际应用示例
package main
import (
"encoding/json"
"fmt"
)
// 定义学生结构体
type Student struct {
ID int `json:"id"`
Name string `json:"name"`
Age int `json:"age"`
Scores []int `json:"scores"`
}
// 计算平均分的方法
func (s Student) Average() float64 {
if len(s.Scores) == 0 {
return 0
}
total := 0
for _, score := range s.Scores {
total += score
}
return float64(total) / float64(len(s.Scores))
}
// 添加成绩的方法
func (s *Student) AddScore(score int) {
s.Scores = append(s.Scores, score)
}
// 获取学生信息的方法
func (s Student) GetInfo() string {
return fmt.Sprintf("学号: %d, 姓名: %s, 年龄: %d, 平均分: %.2f",
s.ID, s.Name, s.Age, s.Average())
}
func main() {
// 创建学生
student := Student{
ID: 1001,
Name: "张三",
Age: 20,
Scores: []int{85, 92, 78, 96},
}
// 使用方法
fmt.Println(student.GetInfo())
// 添加新成绩
student.AddScore(88)
fmt.Printf("添加新成绩后的平均分: %.2f\n", student.Average())
// JSON 序列化
jsonData, err := json.Marshal(student)
if err != nil {
fmt.Printf("JSON 序列化错误: %v\n", err)
return
}
fmt.Printf("JSON 数据: %s\n", jsonData)
// JSON 反序列化
var newStudent Student
err = json.Unmarshal(jsonData, &newStudent)
if err != nil {
fmt.Printf("JSON 反序列化错误: %v\n", err)
return
}
fmt.Printf("反序列化后: %s\n", newStudent.GetInfo())
}
结构体最佳实践
字段命名:使用驼峰命名法,大写字母开头的字段可被包外访问
零值可用:设计结构体时考虑零值是否有意义
嵌入vs组合:优先使用组合而不是嵌入,除非确实需要继承行为
方法接收器:
如果方法需要修改结构体,使用指针接收器
如果结构体很大,使用指针接收器以避免复制
保持一致性:如果有些方法使用指针接收器,其他方法也应该使用
总结
Go 语言的三种基本数据结构各有特点:
切片:动态数组,提供灵活的长度管理
映射:键值对存储,快速查找和访问
结构体:自定义类型,组织相关数据和行为
这些数据结构是 Go 程序的基础构建块,理解和熟练使用它们对于编写高效的 Go 程序至关重要。
结构体 (Struct)
1. 结构体基础
结构体定义和初始化
// 定义结构体
type Person struct {
Name string
Age int
City string
}
// 结构体初始化方式
func structInitialization() {
// 方式1: 字段名初始化
p1 := Person{
Name: "Alice",
Age: 25,
City: "New York",
}
// 方式2: 按顺序初始化
p2 := Person{"Bob", 30, "London"}
// 方式3: 部分初始化
p3 := Person{Name: "Charlie", Age: 28}
// 方式4: 使用 new
p4 := new(Person)
p4.Name = "David"
p4.Age = 35
}
结构体方法
// 值接收者方法
func (p Person) GetInfo() string {
return fmt.Sprintf("Name: %s, Age: %d, City: %s", p.Name, p.Age, p.City)
}
// 指针接收者方法
func (p *Person) SetAge(age int) {
p.Age = age
}
func (p *Person) HaveBirthday() {
p.Age++
}
// 使用示例
func main() {
person := Person{Name: "Alice", Age: 25, City: "New York"}
// 调用值接收者方法
fmt.Println(person.GetInfo())
// 调用指针接收者方法
person.SetAge(26)
person.HaveBirthday()
fmt.Printf("New age: %d\n", person.Age) // 输出: 27
}
2. 结构体高级特性
嵌入结构体
type Address struct {
Street string
City string
Country string
}
type Employee struct {
Person // 嵌入 Person 结构体
Address // 嵌入 Address 结构体
Salary float64
Company string
}
func embeddedStructs() {
emp := Employee{
Person: Person{
Name: "John",
Age: 30,
},
Address: Address{
Street: "123 Main St",
City: "Boston",
Country: "USA",
},
Salary: 50000,
Company: "TechCorp",
}
// 可以直接访问嵌入结构体的字段
fmt.Println(emp.Name) // 来自 Person
fmt.Println(emp.City) // 来自 Address
fmt.Println(emp.Salary) // Employee 自己的字段
}
结构体标签
import (
"encoding/json"
"fmt"
)
type User struct {
ID int `json:"id"`
Username string `json:"username"`
Email string `json:"email,omitempty"`
Password string `json:"-"` // 不会被序列化
}
func structTags() {
user := User{
ID: 1,
Username: "alice",
Email: "alice@example.com",
Password: "secret123",
}
// JSON 序列化
jsonData, _ := json.Marshal(user)
fmt.Println(string(jsonData))
// 输出: {"id":1,"username":"alice","email":"alice@example.com"}
}
3. 实际应用示例
学生管理系统
type Student struct {
ID int
Name string
Grades map[string]int
Address Address
}
func (s *Student) AddGrade(subject string, grade int) {
if s.Grades == nil {
s.Grades = make(map[string]int)
}
s.Grades[subject] = grade
}
func (s Student) GetAverageGrade() float64 {
if len(s.Grades) == 0 {
return 0
}
total := 0
for _, grade := range s.Grades {
total += grade
}
return float64(total) / float64(len(s.Grades))
}
func (s Student) GetGradeReport() string {
var report string
report += fmt.Sprintf("Student: %s (ID: %d)\n", s.Name, s.ID)
report += "Grades:\n"
for subject, grade := range s.Grades {
report += fmt.Sprintf(" %s: %d\n", subject, grade)
}
report += fmt.Sprintf("Average: %.2f\n", s.GetAverageGrade())
return report
}
// 使用示例
func studentManagementExample() {
student := Student{
ID: 1,
Name: "Alice Johnson",
Address: Address{
Street: "456 Oak Ave",
City: "Boston",
Country: "USA",
},
}
student.AddGrade("Math", 95)
student.AddGrade("English", 87)
student.AddGrade("Science", 92)
fmt.Println(student.GetGradeReport())
}
作者:admin 创建时间:2025-09-23 22:24
最后编辑:admin 更新时间:2025-09-24 00:14
最后编辑:admin 更新时间:2025-09-24 00:14