ZetCode

Golang struct 关键字

最后修改于 2025 年 5 月 7 日

本教程将介绍如何在 Go 中使用 struct 关键字。我们将通过创建和使用自定义类型的实际示例来涵盖 struct 的基础知识。

struct 关键字定义了一个复合数据类型,它将多个变量组合在一个名称下。Structs 是在 Go 中创建复杂数据结构的基础。

在 Go 中,structs 可以包含不同类型的字段、方法,并且可以实现接口。它们提供了一种创建自定义类型的方式,用于模拟现实世界中的实体和关系。

基本 struct 定义

最简单的 struct 包含带有其类型的命名字段。本示例展示了如何定义和初始化一个基本的 struct。

basic_struct.go
package main

import "fmt"

type Person struct {
    Name string
    Age  int
}

func main() {
    var p1 Person
    p1.Name = "Alice"
    p1.Age = 30
    
    p2 := Person{"Bob", 25}
    
    fmt.Println(p1)
    fmt.Println(p2)
}

我们定义了一个带有 NameAge 字段的 Person struct。示例展示了两种初始化方法:逐个字段初始化和使用 struct 字面量。

匿名 structs

Go 支持匿名 structs,用于一次性使用场景。本示例演示了创建和使用未命名 struct 类型。

anonymous_struct.go
package main

import "fmt"

func main() {
    book := struct {
        Title  string
        Author string
        Pages  int
    }{
        Title:  "The Go Programming Language",
        Author: "Alan Donovan",
        Pages:  380,
    }
    
    fmt.Printf("%+v\n", book)
}

匿名 struct 在一步中定义和初始化。当您需要一个临时结构而无需声明新类型时,这很有用。

嵌套 structs

Structs 可以包含其他 structs 来模拟复杂的关系。本示例展示了嵌套 struct 的组合。

nested_struct.go
package main

import "fmt"

type Address struct {
    Street  string
    City    string
    Country string
}

type Person struct {
    Name    string
    Age     int
    Address Address
}

func main() {
    p := Person{
        Name: "Charlie",
        Age:  35,
        Address: Address{
            Street:  "123 Main St",
            City:    "Boston",
            Country: "USA",
        },
    }
    
    fmt.Printf("%+v\n", p)
}

Person struct 包含一个 Address struct。这创建了一个模拟现实世界关系的层次数据结构。

Struct 方法

Structs 可以附加方法。本示例演示了在 struct 类型上定义和调用方法。

struct_methods.go
package main

import "fmt"

type Rectangle struct {
    Width  float64
    Height float64
}

func (r Rectangle) Area() float64 {
    return r.Width * r.Height
}

func (r *Rectangle) Scale(factor float64) {
    r.Width *= factor
    r.Height *= factor
}

func main() {
    rect := Rectangle{Width: 10, Height: 5}
    fmt.Println("Area:", rect.Area())
    
    rect.Scale(2)
    fmt.Println("Scaled Area:", rect.Area())
}

Area 方法使用值接收器,而 Scale 使用指针接收器。指针接收器可以修改原始 struct。

Struct 标签

Struct 标签提供关于字段的元数据。本示例展示了用于序列化的 JSON 标签。

struct_tags.go
package main

import (
    "encoding/json"
    "fmt"
)

type User struct {
    ID        int    `json:"id"`
    Username  string `json:"username"`
    Email     string `json:"email,omitempty"`
    IsActive  bool   `json:"-"`
}

func main() {
    u := User{
        ID:       1,
        Username: "johndoe",
        Email:    "",
        IsActive: true,
    }
    
    data, _ := json.Marshal(u)
    fmt.Println(string(data))
}

标签控制 JSON 字段名称和行为。omitempty 用于跳过空字段,而 - 用于从序列化中排除字段。

Struct 嵌入

Go 支持通过嵌入 structs 来实现组合。本示例演示了字段和方法的提升。

struct_embedding.go
package main

import "fmt"

type Contact struct {
    Email string
    Phone string
}

func (c Contact) Info() string {
    return fmt.Sprintf("%s | %s", c.Email, c.Phone)
}

type Employee struct {
    Name string
    Contact
}

func main() {
    emp := Employee{
        Name: "Jane Doe",
        Contact: Contact{
            Email: "jane@example.com",
            Phone: "555-1234",
        },
    }
    
    fmt.Println(emp.Info())
    fmt.Println(emp.Email)
}

Contact 的字段和方法被提升到 Employee struct。这提供了一种在没有继承的情况下组合功能的方式。

Struct 比较

如果所有字段都可比较,则 structs 可以进行比较。本示例展示了 struct 实例之间的相等性检查。

struct_comparison.go
package main

import "fmt"

type Point struct {
    X, Y int
}

func main() {
    p1 := Point{1, 2}
    p2 := Point{1, 2}
    p3 := Point{2, 3}
    
    fmt.Println("p1 == p2:", p1 == p2)
    fmt.Println("p1 == p3:", p1 == p3)
    
    type Person struct {
        Name string
        Age  int
    }
    
    // person1 := Person{"Alice", 30}
    // person2 := Person{"Alice", 30}
    // fmt.Println(person1 == person2) // Valid
    
    // type Data struct {
    //     Info map[string]string
    // }
    // d1 := Data{Info: make(map[string]string)}
    // d2 := Data{Info: make(map[string]string)}
    // fmt.Println(d1 == d2) // Invalid: map fields are not comparable
}

具有可比较字段的 structs 可以使用 == 进行比较。该示例还显示了由于不可比较字段而无法进行比较的情况。

来源

Go 语言规范

本教程通过创建和使用自定义数据结构的实际示例,涵盖了 Go 中的 struct 关键字。

作者

我的名字是 Jan Bodnar,我是一位充满热情的程序员,拥有丰富的编程经验。自 2007 年以来,我一直在撰写编程文章。迄今为止,我已撰写了 1,400 多篇文章和 8 本电子书。我在教授编程方面拥有超过十年的经验。

列出所有 Golang 教程