结构体基础 #

一、结构体概述 #

结构体是一种聚合数据类型,将多个字段组合成一个整体。

二、结构体定义 #

2.1 基本语法 #

go
type Person struct {
    Name string
    Age  int
    City string
}

2.2 字段命名 #

  • 首字母大写:公开字段(可导出)
  • 首字母小写:私有字段
go
type User struct {
    Name   string  // 公开
    email  string  // 私有
}

2.3 相同类型字段 #

go
type Point struct {
    X, Y int
}

2.4 空结构体 #

go
type Empty struct{}

var e Empty
fmt.Println(unsafe.Sizeof(e))  // 0

三、结构体初始化 #

3.1 零值初始化 #

go
var p Person
fmt.Println(p.Name)  // ""(零值)
fmt.Println(p.Age)   // 0(零值)

3.2 字面量初始化 #

go
p := Person{
    Name: "Alice",
    Age:  25,
    City: "Beijing",
}

3.3 按顺序初始化 #

go
p := Person{"Alice", 25, "Beijing"}

3.4 部分初始化 #

go
p := Person{
    Name: "Alice",
    Age:  25,
    // City为零值
}

3.5 new函数 #

go
p := new(Person)
fmt.Printf("%T\n", p)  // *Person
fmt.Println(p.Name)    // ""(零值)

四、字段访问 #

4.1 值访问 #

go
p := Person{Name: "Alice", Age: 25}

fmt.Println(p.Name)  // Alice
fmt.Println(p.Age)   // 25

4.2 指针访问 #

go
p := &Person{Name: "Alice", Age: 25}

fmt.Println(p.Name)   // Alice(自动解引用)
fmt.Println((*p).Name) // Alice(显式解引用)

4.3 修改字段 #

go
p := Person{Name: "Alice"}
p.Name = "Bob"
fmt.Println(p.Name)  // Bob

五、结构体指针 #

5.1 创建指针 #

go
p := &Person{Name: "Alice"}

// 或
p := new(Person)
p.Name = "Alice"

5.2 函数传递 #

go
func modify(p *Person) {
    p.Name = "Modified"
}

func main() {
    p := Person{Name: "Alice"}
    modify(&p)
    fmt.Println(p.Name)  // Modified
}

5.3 返回指针 #

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

p := NewPerson("Alice", 25)

六、结构体比较 #

6.1 可比较 #

如果所有字段都可比较,结构体可比较:

go
p1 := Person{Name: "Alice", Age: 25}
p2 := Person{Name: "Alice", Age: 25}
p3 := Person{Name: "Bob", Age: 25}

fmt.Println(p1 == p2)  // true
fmt.Println(p1 == p3)  // false

6.2 不可比较字段 #

包含切片、映射、函数的结构体不可比较:

go
type Data struct {
    Values []int
}

d1 := Data{Values: []int{1, 2, 3}}
d2 := Data{Values: []int{1, 2, 3}}

fmt.Println(d1 == d2)  // 编译错误

七、结构体作为字段 #

7.1 命名嵌入 #

go
type Address struct {
    City    string
    Country string
}

type Person struct {
    Name    string
    Address Address
}

p := Person{
    Name: "Alice",
    Address: Address{
        City:    "Beijing",
        Country: "China",
    },
}

fmt.Println(p.Address.City)  // Beijing

7.2 匿名嵌入 #

go
type Person struct {
    Name string
    Address  // 匿名嵌入
}

p := Person{
    Name: "Alice",
    Address: Address{
        City: "Beijing",
    },
}

fmt.Println(p.City)  // Beijing(字段提升)

八、结构体方法 #

8.1 值接收者 #

go
func (p Person) GetName() string {
    return p.Name
}

p := Person{Name: "Alice"}
fmt.Println(p.GetName())  // Alice

8.2 指针接收者 #

go
func (p *Person) SetName(name string) {
    p.Name = name
}

p := &Person{Name: "Alice"}
p.SetName("Bob")
fmt.Println(p.Name)  // Bob

九、工厂函数 #

9.1 构造函数 #

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

p := NewPerson("Alice", 25)

9.2 带验证的构造函数 #

go
func NewPerson(name string, age int) (*Person, error) {
    if name == "" {
        return nil, errors.New("name cannot be empty")
    }
    if age < 0 {
        return nil, errors.New("age cannot be negative")
    }
    return &Person{Name: name, Age: age}, nil
}

十、实际应用 #

10.1 配置结构体 #

go
type Config struct {
    Host     string
    Port     int
    Database string
    Timeout  time.Duration
}

func NewDefaultConfig() *Config {
    return &Config{
        Host:     "localhost",
        Port:     8080,
        Database: "mydb",
        Timeout:  30 * time.Second,
    }
}

10.2 响应结构体 #

go
type Response struct {
    Code    int         `json:"code"`
    Message string      `json:"message"`
    Data    interface{} `json:"data"`
}

func Success(data interface{}) *Response {
    return &Response{
        Code:    200,
        Message: "success",
        Data:    data,
    }
}

十一、总结 #

结构体要点:

特性 说明
定义 type Name struct
初始化 字面量、new函数
访问 点号访问字段
比较 可比较字段可比较
指针 支持指针接收者方法

关键点:

  1. 聚合类型:组合多个字段
  2. 值类型:赋值和传参复制
  3. 字段可见性:首字母大小写控制
  4. 方法:可以为结构体定义方法
  5. 工厂函数:推荐使用构造函数

准备好学习结构体方法了吗?让我们进入下一章!

最后更新:2026-03-26