在 Go 语言中,结构体(struct)是一种聚合数据类型,用于将不同类型的数据组合在一起。结构体非常适合用于表示具有多个属性的复杂数据对象。每个属性称为字段(field),字段可以是任何类型,包括基本数据类型、数组、切片、指针甚至其他结构体。

Go 语言没有类(class)这一概念,但结构体的功能可以替代类,用于定义对象和组织数据。


📖 目录

  1. 结构体定义
  2. 结构体初始化
  3. 结构体访问
  4. 结构体指针
  5. 结构体方法
  6. 匿名结构体
  7. 结构体嵌套
  8. 结构体与接口
  9. 结构体与 JSON
  10. 总结
  11. 参考资料

1. 结构体定义

结构体定义使用 type 关键字,之后是结构体的名字和结构体字段。字段可以是任意数据类型,也可以是其他结构体类型。

示例:

package main

import "fmt"

// 定义一个结构体类型 Person
type Person struct {
    Name string
    Age  int
}

func main() {
    // 创建一个结构体实例
    p := Person{Name: "Alice", Age: 30}
    fmt.Println(p)
}

输出:

{Alice 30}

在这个例子中,定义了一个 Person 结构体,它有两个字段 NameAge,然后通过 Name: "Alice", Age: 30 初始化了结构体实例。


2. 结构体初始化

结构体的初始化可以通过几种方式完成,包括按字段名初始化和匿名初始化。

2.1 按字段名初始化

p := Person{Name: "Bob", Age: 25}

2.2 使用构造函数初始化

如果结构体有多个字段,使用构造函数可以避免顺序错误。

func NewPerson(name string, age int) Person {
    return Person{Name: name, Age: age}
}

p := NewPerson("Charlie", 35)

2.3 匿名初始化

p := Person{"Dave", 40}  // 顺序初始化

顺序初始化要求字段的顺序与定义时的顺序一致,但不如按字段名初始化清晰。


3. 结构体访问

Go 语言中,结构体的字段可以通过点(.)运算符访问。

示例:

package main

import "fmt"

type Person struct {
    Name string
    Age  int
}

func main() {
    p := Person{"Eve", 22}
    fmt.Println(p.Name)  // 访问字段 Name
    fmt.Println(p.Age)   // 访问字段 Age
}

输出:

Eve
22


4. 结构体指针

Go 中的结构体是值类型,通过指针传递结构体可以避免复制结构体的值。结构体指针可以通过 & 获取,也可以使用 new 函数创建。

示例:

package main

import "fmt"

type Person struct {
    Name string
    Age  int
}

func main() {
    p := Person{"Frank", 45}
    ptr := &p  // 获取结构体指针

    // 使用指针访问字段
    fmt.Println(ptr.Name) // 输出: Frank
    fmt.Println(ptr.Age)  // 输出: 45
}


5. 结构体方法

Go 语言允许为结构体类型定义方法。这些方法可以与结构体类型相关联,并能操作结构体的字段。

示例:

package main

import "fmt"

type Person struct {
    Name string
    Age  int
}

// 为 Person 类型定义一个方法
func (p Person) Greet() {
    fmt.Println("Hello, my name is", p.Name)
}

func main() {
    p := Person{"Grace", 28}
    p.Greet()  // 调用结构体方法
}

输出:

Hello, my name is Grace

方法接收者

  • 值接收者func (p Person) Greet(),在调用方法时会复制结构体实例。
  • 指针接收者func (p *Person) Greet(),这样方法可以修改结构体的字段。

示例(指针接收者):

func (p *Person) HaveBirthday() {
    p.Age++
}

func main() {
    p := Person{"Grace", 28}
    p.HaveBirthday()  // 调用修改方法
    fmt.Println(p.Age)  // 输出: 29
}


6. 匿名结构体

匿名结构体是没有定义名称的结构体,通常用于临时存储数据。

示例:

package main

import "fmt"

func main() {
    // 创建一个匿名结构体并初始化
    p := struct {
        Name string
        Age  int
    }{"Hannah", 26}

    fmt.Println(p.Name)  // 输出: Hannah
    fmt.Println(p.Age)   // 输出: 26
}

匿名结构体在快速构建临时数据时很有用,但它们通常不用于长期的数据模型。


7. 结构体嵌套

Go 支持结构体嵌套。一个结构体可以包含另一个结构体作为字段。

示例:

package main

import "fmt"

type Address struct {
    Street string
    City   string
}

type Person struct {
    Name    string
    Age     int
    Address Address  // 嵌套结构体
}

func main() {
    p := Person{
        Name: "Jack",
        Age:  32,
        Address: Address{
            Street: "123 Elm St",
            City:   "Metropolis",
        },
    }

    fmt.Println(p.Name)         // 输出: Jack
    fmt.Println(p.Address.City) // 输出: Metropolis
}


8. 结构体与接口

Go 语言的接口和结构体可以结合使用,实现多态。任何类型只要实现了接口的所有方法,就被认为实现了该接口。

示例:

package main

import "fmt"

type Speaker interface {
    Speak()
}

type Person struct {
    Name string
}

func (p Person) Speak() {
    fmt.Println("Hello, my name is", p.Name)
}

func introduce(speaker Speaker) {
    speaker.Speak()
}

func main() {
    p := Person{"Oliver"}
    introduce(p)  // 调用接口方法
}


9. 结构体与 JSON

Go 语言中的结构体可以通过 encoding/json 包来与 JSON 数据进行转换。使用结构体标签(json:"field_name")可以指定 JSON 的键。

示例:

package main

import (
    "encoding/json"
    "fmt"
)

type Person struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}

func main() {
    p := Person{"Lily", 33}
    jsonData, _ := json.Marshal(p)
    fmt.Println(string(jsonData))  // 输出: {"name":"Lily","age":33}
}


10. 总结

  • 结构体是 Go 中一种用于组织数据的聚合类型,适合表示具有多个字段的数据。
  • 结构体可以通过字段名初始化,也可以使用匿名初始化。
  • 结构体的字段可以通过点操作符访问,指针则允许我们直接修改结构体的内容。
  • Go 语言中的结构体方法使得结构体与函数的行为紧密结合。
  • 结构体可以嵌套,成为更复杂的数据结构。
  • 结构体可以与接口配合实现多态,进一步扩展其应用。
  • 结构体还可以与 JSON 进行互转,方便与外部数据交互。

11. 参考资料


结构体是 Go 语言中非常强大的工具,用于组织和表示复杂数据结构。通过与方法、接口的结合,结构体能够灵活地实现丰富的功能。