跳转到内容

Go 结构体

来自代码酷

Go结构体[编辑 | 编辑源代码]

结构体(Struct)是Go语言中一种重要的复合数据类型,它允许开发者将不同类型的变量组合成一个逻辑单元。结构体是面向对象编程中"对象"的基础,用于表示现实世界中的实体及其属性。

基本概念[编辑 | 编辑源代码]

结构体是由一系列字段(Fields)组成的集合,每个字段都有名称和类型。结构体定义了一个新的数据类型,可以用来创建该类型的变量(称为结构体实例)。

定义结构体[编辑 | 编辑源代码]

结构体使用typestruct关键字定义:

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{}作为空结构体可以节省内存(常用于信号传递)

结构体内存布局[编辑 | 编辑源代码]

结构体在内存中是连续存储的,字段按照定义的顺序排列:

graph LR A[结构体起始地址] --> B[字段1] B --> C[字段2] C --> D[...] D --> E[字段N]

内存对齐规则:

  • 字段偏移量通常是其大小和对齐要求的倍数
  • 编译器可能会插入填充字节以满足对齐要求

总结[编辑 | 编辑源代码]

Go结构体是构建复杂数据类型的基石,具有以下特点:

  • 组合而非继承的设计哲学
  • 灵活的内存布局控制
  • 与接口协同实现多态
  • 高效的数据封装能力

掌握结构体是成为熟练Go开发者的关键一步,它在系统编程、Web开发和分布式系统等领域都有广泛应用。