Go 结构体高级用法

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


匿名结构体(Anonymous structs)

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

go 复制代码
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)

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

go 复制代码
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)

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

go 复制代码
type Country struct {
    string
    int
}

代码解析

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

  • 给匿名字段赋值:

go 复制代码
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)

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

go 复制代码
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 结构体:

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

对应 Go 结构体:

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 的结构体了。

相关推荐
BingoGo2 小时前
PHP 8.6 新增 clamp() 函数
后端·php
csdn_life182 小时前
Rustrover 如何像Java一样直接 进行调试和运行
java·开发语言·rust
风象南2 小时前
Spring Boot 打造通用CLI命令系统
后端
草莓熊Lotso3 小时前
C++11 核心特性实战:列表初始化 + 右值引用与移动语义(附完整代码)
java·服务器·开发语言·汇编·c++·人工智能·经验分享
初夏睡觉4 小时前
从0开始c++,但是重置版,第1篇(c++基本框架)
开发语言·c++
workflower9 小时前
时序数据获取事件
开发语言·人工智能·python·深度学习·机器学习·结对编程
CoderYanger10 小时前
C.滑动窗口-求子数组个数-越长越合法——2799. 统计完全子数组的数目
java·c语言·开发语言·数据结构·算法·leetcode·职场和发展
C++业余爱好者10 小时前
Java 提供了8种基本数据类型及封装类型介绍
java·开发语言·python
想用offer打牌10 小时前
RocketMQ如何防止消息丢失?
java·后端·架构·开源·rocketmq