Go 结构体高级用法

今天我们继续讨论关于 struct(结构体) 的内容。在本主题中,你将学习结构体的高级使用概念:匿名结构体、嵌套结构体(即结构体中包含另一个或多个结构体作为字段)、匿名字段、提升字段以及 Go 中的结构体标签(struct tags)。


匿名结构体(Anonymous structs)

之前我们讲过基本的结构体类型声明,需要先创建一个新的数据类型。然而,我们也可以声明一个 不创建新数据类型的结构体,这种结构体称为 匿名结构体。看一个例子:

package main

import "fmt"

var teslaModelS = struct {
    Brand, Model, Color string
    weightInKg          int
}{
    Brand:      "Tesla",
    Model:      "Model S",
    Color:      "Red",
    weightInKg: 2250,
}

func main() {
    fmt.Println(teslaModelS) // {Tesla Model S Red 2250}
}

代码解析
上面,我们声明了一个匿名结构体 teslaModelS,分三步完成:

  1. 使用 var teslaModelS = struct 的语法;

  2. 在大括号 {} 内声明它的字段;

  3. 使用结构体字面量(struct literal)初始化字段。

注意:匿名结构体必须立即附带一个结构体字面量初始化它的字段,否则编译器会报错,提示匿名结构体不是一个表达式。

作用

  • 匿名结构体提供了快速创建结构体而无需新建类型的方式。

  • 如果某个结构体只在程序中使用一次,使用匿名结构体能避免意外重复使用。

  • 匿名结构体常用于 表驱动的单元测试(table-driven unit tests)


嵌套结构体(Nested structs)

结构体可以组合不同的数据类型,所以一个结构体可以包含一个或多个结构体作为字段。来看一个例子:

type Address struct {
    City  string
    State string
}

type Employee struct {
    Name    string
    Age     int
    Salary  float64
    Address Address // 嵌套的 Address 结构体
}

func main() {
    homer := Employee{
        Name:    "Homer",
        Age:     39,
        Salary:  724.38,
        Address: Address{City: "Springfield", State: "Oregon"},
    }

    fmt.Println("City:", homer.Address.City)   // City: Springfield
    fmt.Println("State:", homer.Address.State) // State: Oregon
}

代码解析
Employee 结构体中声明了 Address 字段后,可以通过两次使用 . 操作符访问嵌套结构体的字段。


匿名字段(Anonymous fields)

结构体可以有只声明类型而不写字段名的字段,这种字段叫做 匿名字段。举个例子:

type Country struct {
    string
    int
}

代码解析

  • 虽然匿名字段没有字段名,但默认会以它的数据类型作为字段名。

  • 给匿名字段赋值:

var france Country
france.string = "France"
france.int = 67413000

fmt.Println("Country name:", france.string) // Country name: France
fmt.Println("Population:", france.int)      // Population: 67413000

注意

  • 一个数据类型只能有一个匿名字段,否则会报错,比如两个 string 类型匿名字段会出现重复字段错误。

提升字段(Promoted fields)

提升字段是指结构体中 匿名结构体字段的字段,我们可以直接通过外层结构体访问它们。例子:

package main

import "fmt"

type Address struct {
	City string
	State string
}
type Employee struct {
    Name   string
    Age    int
    Salary float64
    Address // 匿名字段,不写名字
}

func main() {
    var homer Employee
    homer.Name = "Homer"
    homer.Age = 39
    homer.Salary = 724.38
    
    // 直接访问 Address 中的字段
    homer.City = "Springfield"
    homer.State = "Oregon"

    fmt.Println("City:", homer.City)   // City: Springfield
    fmt.Println("State:", homer.State) // State: Oregon
}

代码解析
由于 Address 是匿名字段,我们可以直接访问其字段 CityState,就像它们属于 Employee 结构体一样。


结构体标签(Struct tags)

Go 允许在结构体字段后添加 结构体标签(struct tags)。最常见的用途是控制 JSON 编码。例如,将以下 JSON 数据映射到 Go 结构体:

{
  "userID": "123",
  "isActive": true,
  "lastLogin": "2021-12-08T11:27:32.834056-05:00",
  "userType": 1
}

对应 Go 结构体:

type User struct {
    UserID    string    `json:"userID"`
    IsActive  bool      `json:"isActive"`
    LastLogin time.Time `json:"lastLogin"`
    UserType  int       `json:"userType"`
}

代码解析

  • 结构体标签必须用反引号 ` 包裹;

  • 标签格式为 key:"value",key 通常表示编码库(如 json);

  • value 表示对应的字段名,用于 JSON 编码或其他第三方库。

除了 JSON 标签,还有其他类型的结构体标签可以使用。


总结

本节我们学习了结构体的高级使用方法,包括:

  1. 如何创建匿名结构体及其常见用途;

  2. 如何创建嵌套结构体以及访问嵌套字段;

  3. 匿名字段的使用及限制;

  4. 提升字段的概念及直接访问方式;

  5. 结构体标签及其在 JSON 编码中的应用。

通过这些知识,你就能更灵活、高效地使用 Go 的结构体了。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值