Go 语言中的结构体

GolangGolangBeginner
立即练习

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

介绍

结构体(struct)是一种复合类型,可用于存储不同类型的数据。它可以用来实现更复杂的数据结构。例如,便利店中的商品具有产品名称、类别和价格等属性。我们可以使用结构体来表示它们。

在本实验中,我们将学习如何定义和使用结构体。

知识点:

  • 结构体的定义
  • 结构体实例的方法

Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL go(("Golang")) -.-> go/BasicsGroup(["Basics"]) go(("Golang")) -.-> go/DataTypesandStructuresGroup(["Data Types and Structures"]) go(("Golang")) -.-> go/ObjectOrientedProgrammingGroup(["Object-Oriented Programming"]) go/BasicsGroup -.-> go/values("Values") go/BasicsGroup -.-> go/variables("Variables") go/DataTypesandStructuresGroup -.-> go/structs("Structs") go/DataTypesandStructuresGroup -.-> go/pointers("Pointers") go/ObjectOrientedProgrammingGroup -.-> go/methods("Methods") subgraph Lab Skills go/values -.-> lab-149097{{"Go 语言中的结构体"}} go/variables -.-> lab-149097{{"Go 语言中的结构体"}} go/structs -.-> lab-149097{{"Go 语言中的结构体"}} go/pointers -.-> lab-149097{{"Go 语言中的结构体"}} go/methods -.-> lab-149097{{"Go 语言中的结构体"}} end

结构体的定义

我们可以使用关键字 typestruct 来定义一个结构体。语法如下:

type StructName struct {
    FieldName Type
    // ...
}

其中:

  • Type 表示字段名称的具体类型,可以是整数、字符串等。
  • StructName 必须在同一个包内唯一。
  • 字段名称 必须在同一个结构体内唯一。

让我们来尝试一下。我们定义一个便利店:

type Store struct {
    ProductType string // 产品类型
    ProductName string // 产品名称
    Price       int    // 产品价格
}

在上面的代码中,我们为便利店定义了一个名为 Store 的结构体,其中包含产品的类型、名称和价格。

由于产品类型和产品名称字段的类型相同,我们可以将代码简化为如下形式:

type Store struct {
    ProductName, ProductType string
    Price                   int
}

使用 var 进行实例化

在上一节中,我们定义了一个便利店结构体 Store,它描述了内存空间。只有在实例化后,才会分配内存并使用结构体的字段。

我们可以使用 var 关键字来实例化一个结构体:

var InstanceName Structure

让我们来看一个实例化的例子。创建一个名为 struct.go 的文件,并编写以下代码:

cd ~/project
touch struct.go
package main

import "fmt"

type Store struct {
    productName string
    productType string
    price       int
}

func main() {
    // 使用 `var` 实例化一个结构体
    var store1 Store
    // 为实例 store1 的相关字段赋值
    store1.productType = "Drinks"
    store1.productName = "Coca-Cola"
    store1.price = 3

    fmt.Printf("store1:\n\t%s\n\t%s\n\t%d\n",
        store1.productType, store1.productName, store1.price)
}

运行程序:

go run struct.go

运行后,显示以下结果:

store1:
Drinks
Coca-Cola
3

在这个程序中,我们使用 var 实例化了一个便利店,然后使用 . 操作符为其字段赋值。

结构体的初始值

如果我们只初始化一个结构体而不赋值,其实例化后的值会是什么?让我们来看以下代码:

package main

import "fmt"

type Store struct {
    ProductName string
    ProductType string
    Price       int
}

func main() {
    // 使用 `var` 实例化一个结构体
    var lan1 Store
    // 使用 %#v 打印结构体的值
    fmt.Printf("lan1: %#v\n", lan1)
}

运行程序:

go run struct.go

结果如下:

lan1: main.Store{ProductName:"", ProductType:"", Price:0}

我们可以看到,当没有指定初始值时,实例化的结构体的值是对应类型的零值。例如,字符串为空,整数为 0。

使用 new 进行实例化

除了使用 var 关键字进行实例化外,我们还可以使用 new 关键字:

package main

import "fmt"

type Store struct {
    productName string
    productType string
    price       int
}

func main() {
    store := new(Store)
    // 使用 %T 输出类型
    fmt.Printf("Type of store: %T\n", store)

    store.productType = "Daily Necessities"
    store.productName = "Umbrella"
    store.price = 20

    fmt.Printf("store:\n\t%s\n\t%s\n\t%d\n",
        store.productType, store.productName, store.price)
}

运行程序:

go run struct.go

结果如下:

Type of store: *main.Store
store:
        Daily Necessities
        Umbrella
        20

当使用 new 关键字进行实例化时,它创建的“实例”实际上是指向实例的指针。对结构体指针的赋值操作与对普通结构体的赋值操作相同。

使用 := 进行实例化

同样地,我们可以使用 := 来实例化一个结构体:

package main

import "fmt"

type Store struct {
    productName string
    productType string
    price       int
}

func main() {
    lan3 := Store{}
    lan3.productType = "Fresh Food"
    lan3.productName = "Taiwanese Meatballs"
    lan3.price = 20
    fmt.Printf("lan3:\n\t%s\n\t%s\n\t%d\n",
        lan3.productType, lan3.productName, lan3.price)
}

运行程序:

go run struct.go

结果如下:

lan3:
    Fresh Food
    Taiwanese Meatballs
    20

我们可以将初始化赋值写在一起,像这样:

package main

import "fmt"

type Store struct {
    productName string
    productType string
    price       int
}

func main() {
    lan3 := Store{
        productType: "Fresh Food",
        productName: "Taiwanese Meatballs",
        price:       4,
    }
    fmt.Printf("lan3:\n\t%s\n\t%s\n\t%d\n",
        lan3.productType, lan3.productName, lan3.price)
}

运行程序:

go run struct.go

结果如下:

lan3:
    Fresh Food
    Taiwanese Meatballs
    4

当我们需要为结构体的所有字段赋值时,可以按照结构体中字段定义的顺序来写值。

例如,我们可以将 lan3 实例重写如下:

lan3 := Store{
        "Fresh Food",
        "Taiwanese Meatballs",
        4,
    }

注意:这种语法仅适用于为所有字段赋值的情况。

总结

在本实验中,我们介绍了结构体并总结了以下知识点:

  • 结构体是复合数据类型,可以包含多个不同的数据类型。
  • 未初始化的结构体的值是对应类型的零值。
  • 实例化结构体的三种方法。