当前位置: 首页 > news >正文

Go 语言中的结构体

我们刚刚学习了方法(Methods)和接口(Interfaces),而它们几乎总是与结构体(Structs)一起使用。可以说,结构体是 Go 语言中组织数据的基石,理解它至关重要。

它扮演的角色非常像 PHP 中的 class,但只负责封装数据(属性),不直接包含方法。

我们同样分场景,从简单到高阶来介绍它,并首先回答你最关心的问题。


核心:如何判断属性是否可被外部访问?(可见性规则)

在 PHP 中,我们用 public, private, protected 关键字来控制属性和方法的可见性。

Go 的规则要简单得多,并且只有一个标准:根据名称的首字母大小写来判断

  • 首字母大写 (Exported):如果一个结构体的字段(或任何顶层变量、函数、类型)以大写字母开头,那么它就是导出的(Exported),相当于 PHP 的 public。这意味着在**任何其他包(package)**中都可以直接访问它。

  • 首字母小写 (Unexported):如果字段以小写字母开头,那么它就是未导出的(Unexported),类似于 PHP 的 private。它只能在同一个包内部被访问。

举个例子:

假设我们有一个 models 包,里面定义了一个 User 结构体:

// in package models
package modelstype User struct {ID        int    // 大写,公开的FirstName string // 大写,公开的lastName  string // 小写,私有的password  string // 小写,私有的
}

现在,我们在 main 包(另一个包)中使用它:

// in package main
package mainimport "myproject/models"func main() {u := models.User{}u.ID = 101           // 正确!ID 是大写的,可以访问u.FirstName = "Alice" // 正确!FirstName 是大写的,可以访问// u.lastName = "Smith" // 编译错误!lastName 在包外不可见// u.password = "123"   // 编译错误!password 在包外不可见
}

这个规则简单、一致,适用于 Go 中所有需要控制可见性的地方。


场景一:基础用法

1. 聚合相关数据

这是 struct 最基本、最核心的用途:将一堆相关的变量组合成一个单一的、有意义的逻辑单元。

  • 场景:
    • 定义一个“用户”,包含姓名、年龄、邮箱。
    • 定义一个数据库连接配置,包含主机、端口、用户名、密码。
    • 定义一个 API 响应,包含状态码、消息和数据。
  • 用法:
    type DBConfig struct {Host     stringPort     intUsername stringPassword string
    }func main() {// 创建并初始化一个 DBConfig 实例config := DBConfig{Host:     "localhost",Port:     3306,Username: "root",Password: "password",}fmt.Println("Connecting to host:", config.Host)
    }
    

场景二:中阶用法

2. 结构体嵌套与组合(替代继承)

Go 语言没有 PHP 的 extends 继承。作为替代,Go 提倡使用组合(Composition),通过在一个结构体中嵌套另一个结构体来实现功能的复用和扩展。

  • 场景:

    • 一个“员工 (Employee)”拥有“个人信息 (Person)”的所有属性,同时还有额外的“职位 (Position)”属性。
    • 一个“文章 (Post)”包含一个“作者 (Author)”的信息。
  • 用法:
    有两种嵌套方式:

    a) 作为普通字段嵌套

    type Address struct {City    stringCountry string
    }type Company struct {Name    stringAddress Address // Address 是 Company 的一个普通字段
    }func main() {c := Company{Name: "Google",Address: Address{City:    "Mountain View",Country: "USA",},}// 访问嵌套字段需要逐级访问fmt.Println(c.Address.City)
    }
    

    b) 匿名嵌套 (Embedding)
    通过只写类型而不写字段名,可以将嵌套结构体的字段“提升”到外层,实现类似继承的效果。

    type Person struct {Name stringAge  int
    }type Employee struct {Person            // 匿名嵌套 PersonPosition string
    }func main() {e := Employee{Person: Person{Name: "Alice",Age:  30,},Position: "Engineer",}// 可以直接访问 Person 的字段,就像是 Employee 自己的一样fmt.Println(e.Name)     // 直接访问,而不是 e.Person.Namefmt.Println(e.Position)
    }
    
3. 使用结构体标签 (Struct Tags)

标签是附加在结构体字段上的元数据(metadata)。它们本身对 Go 代码没有影响,但可以被其他库(如 encoding/json)读取,用来指导这些库如何处理这个字段。

  • 场景:
    • 控制一个结构体如何被编码/解码成 JSON 格式(最常用!)。
    • 定义 ORM(对象关系映射)中结构体字段与数据库表列的对应关系。
    • 为字段添加验证规则。
  • 用法: 标签是写在反引号 ` 内的字符串。
    type Product struct {ID          int     `json:"id"`Name        string  `json:"product_name"`Price       float64 `json:"price,omitempty"` // omitempty 表示如果字段值为零值,则忽略它Description string  `json:"-"`               // - 表示永远不要处理这个字段
    }
    
    当你使用 json.MarshalProduct 实例转换为 JSON 时,encoding/json 包会读取这些标签,并生成对应 key 的 JSON。

场景三:高阶用法

4. 零宽度结构体 struct{}

我们在用 map 实现“集合”时已经见过它。因为它不占用任何内存,所以是表达“存在性”或发送“信号”的绝佳工具。

  • 场景:
    • 集合(Set): map[string]struct{},我们只关心键是否存在。
    • 通道信号: 在并发编程中,有时我们只想通知另一个 Goroutine 某件事已经完成,而不需要传递任何实际数据。
  • 用法:
    // 使用 channel 发送一个完成信号
    done := make(chan struct{})go func() {fmt.Println("Worker is running...")// ... do some work ...// 工作完成,发送一个空结构体作为信号done <- struct{}{}
    }()// main goroutine 会在这里阻塞,直到收到信号
    <-done
    fmt.Println("Worker finished.")
    

总而言之,结构体是 Go 程序中数据的“骨架”。你通过定义结构体来构建你的数据模型,然后通过为它附加方法来赋予它行为,最后通过接口来定义它的抽象契约,从而构建出清晰、健壮、可扩展的 Go 应用。

http://www.dtcms.com/a/418512.html

相关文章:

  • Nest 文件上传与下载
  • 2025-9-28学习笔记
  • 深度学习(十三):向量化与矩阵化
  • 矩阵结构体 图片绘制 超级玛丽demo6
  • 承接网站开发 app开发学校网站建设责任书
  • 网站 管理检察内网门户网站建设
  • LeetCode 390 消除游戏
  • 汕头seo建站新品发布会的作用
  • 基于深度学习的CT扫描图像肝脏肿瘤智能检测与分析系统【python源码+Pyqt5界面+数据集+训练代码】
  • Edge 浏览器安装selenium
  • 学习:SSMP整合综合案例(2025
  • 如何有效抵御DDoS攻击:全面应对策略解析
  • mobaxterm软件下载_mobaxterm安装包下载_mobaxterm安装教程下载_mobaxterm网盘下载
  • Spring依赖注入问题清单及解决方案
  • KingbaseES数据库SSL安全传输与数据完整性保护技术详解
  • 微网站如何做如何对网站用户分析
  • Nginx反向代理与负载均衡全解析
  • FPGA学习篇——Verilog学习之全加器的实现
  • 6、Lombok-速查手册:常用注解语法与生成代码对照表
  • app免费模板下载网站电子商务网站建设与管理读后感
  • 大语言模型LLM解决AI幻觉方法的深度分析
  • Spec 工作流
  • Genome Biology | scKAN:连接单细胞数据分析与药物发现的可解释架构
  • Javascript输入输出
  • BEVfusion解读(三)
  • JavaScript身份证号校验算法
  • 【centos生产环境搭建(三)jdk环境配置】
  • HarmonyOS NEXT 5.0 的星闪(NearLink)开发应用案例
  • Redis 入门:高效缓存与数据存储的利器
  • 贝尔利网站免费永久php免备案空间