0

0

Go 结构体:值类型 vs. 指针类型的选择

聖光之護

聖光之護

发布时间:2025-07-14 17:02:01

|

391人浏览过

|

来源于php中文网

原创

go 结构体:值类型 vs. 指针类型的选择

本文旨在深入探讨 Go 语言中结构体嵌套时,使用值类型和指针类型的区别。通过分析内存分配、共享以及适用场景,帮助开发者根据实际需求做出更合理的选择,从而编写出更高效、更易于维护的代码。

在 Go 语言中,结构体是一种复合数据类型,允许我们将不同类型的字段组合在一起。当一个结构体包含另一个结构体时,我们可以选择使用值类型或指针类型来嵌套。这两种方式在内存分配、数据共享等方面存在显著差异,理解这些差异对于编写高效、可靠的 Go 代码至关重要。

值类型嵌套

当一个结构体包含另一个结构体的值类型时,例如:

type foo_ struct {
    st uint8
    nd uint8
}

type bar struct {
    rd  uint8
    foo foo_
}

在这种情况下,bar 结构体中会直接嵌入一个 foo_ 结构体的实例。这意味着,当我们声明一个 bar 类型的变量时,会同时为 rd 字段和 foo 字段分配内存。foo 字段拥有自己的独立内存空间,存储着 foo_ 结构体的数据。

var b bar // 声明 b

此时,b 变量在内存中占据的空间大小为 rd 字段的大小加上 foo 字段的大小。对 b.foo 的修改不会影响到其他任何变量。

指针类型嵌套

与值类型不同,当一个结构体包含另一个结构体的指针类型时,例如:

type barP struct {
    rd  uint8
    foo *foo_
}

barP 结构体中的 foo 字段是一个指向 foo_ 结构体的指针。这意味着,当我们声明一个 barP 类型的变量时,只会为 rd 字段和 foo 指针分配内存。foo 指针本身并不包含 foo_ 结构体的数据,而是存储着 foo_ 结构体实例的内存地址。

var bp barP // 声明 bp
bp.foo = new(foo_) // 分配 bp.foo 指向的 foo_ 结构体实例的内存

在使用 bp.foo 之前,我们需要使用 new 函数或者取地址符 & 来为 foo_ 结构体分配内存,并将内存地址赋值给 bp.foo 指针。如果没有进行分配,bp.foo 的值将为 nil,对其进行解引用会导致程序崩溃。

数据共享:

与值类型不同,多个 barP 类型的变量可以共享同一个 foo_ 结构体实例。这意味着,如果多个 barP 类型的变量的 foo 指针指向同一个 foo_ 结构体实例,那么对该 foo_ 结构体实例的修改将会影响到所有指向它的 barP 变量。

如何选择

选择使用值类型还是指针类型,取决于具体的应用场景和需求。以下是一些指导原则:

  • 数据所有权和生命周期: 如果一个结构体拥有另一个结构体的所有权,并且希望控制其生命周期,那么使用值类型可能更合适。当包含结构体被销毁时,其内部的结构体也会被销毁。
  • 数据共享和修改: 如果需要多个结构体共享同一个数据,并且希望能够通过修改一个结构体来影响其他结构体,那么使用指针类型是更好的选择。
  • 性能考虑: 值类型在赋值和传递时会进行复制,这可能会导致性能开销。指针类型则只传递内存地址,开销较小。但是,如果频繁地对指针进行解引用,也可能会影响性能。
  • 内存占用 指针类型本身只占用较小的内存空间,但是需要额外的内存来存储指向的结构体实例。值类型则直接在包含结构体中分配内存。
  • Nil 值: 指针类型可以为 nil,这可以用来表示某个值不存在或者未初始化。值类型则不能为 nil。

示例:发票系统

以下是一个简单的发票系统的示例,展示了如何根据实际需求选择值类型或指针类型:

type address struct {
    street string
    city   string
}

type warehouse struct {
    address string
}

type invoice struct {
    name      string
    billing   address
    shipping  *address
    warehouse *warehouse
}

在这个例子中,invoice 结构体包含了 billing 字段,类型为 address 的值类型。这意味着每张发票都必须包含一个账单地址。shipping 字段是一个指向 address 结构体的指针,这意味着发货地址是可选的。如果 shipping 为 nil,则表示发货地址与账单地址相同。warehouse 字段也是一个指向 warehouse 结构体的指针,表示发货仓库。由于仓库的数量通常是有限的,因此可以使用指针类型来实现共享。

总结

在 Go 语言中,选择使用值类型还是指针类型来嵌套结构体,是一个重要的设计决策。理解这两种方式的差异,可以帮助我们编写出更高效、更易于维护的代码。希望本文能够帮助读者更好地理解 Go 语言中结构体的使用。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
数据类型有哪几种
数据类型有哪几种

数据类型有整型、浮点型、字符型、字符串型、布尔型、数组、结构体和枚举等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

338

2023.10.31

php数据类型
php数据类型

本专题整合了php数据类型相关内容,阅读专题下面的文章了解更多详细内容。

225

2025.10.31

c语言 数据类型
c语言 数据类型

本专题整合了c语言数据类型相关内容,阅读专题下面的文章了解更多详细内容。

138

2026.02.12

golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

510

2025.06.09

golang结构体方法
golang结构体方法

本专题整合了golang结构体相关内容,请阅读专题下面的文章了解更多。

204

2025.07.04

抖漫入口地址合集
抖漫入口地址合集

本专题整合了抖漫入口地址相关合集,阅读专题下面的文章了解更多详细地址。

1

2026.03.17

多环境下的 Nginx 安装、结构与运维实战
多环境下的 Nginx 安装、结构与运维实战

本专题聚焦多环境下Nginx实战,详解开发、测试及生产环境的差异化安装策略与目录结构规划。深入剖析配置模块化设计、灰度发布流程及跨环境同步机制。结合监控告警、故障排查与自动化运维工具,提供全链路管理方案,助力团队构建灵活、高可用的Nginx服务体系,从容应对复杂业务场景挑战。

0

2026.03.17

PS 批量添加图片
PS 批量添加图片

本专题整合了PS批量添加图片教程合集,阅读专题下面的文章了解更多详细操作。

0

2026.03.17

Nginx 基础架构:从安装配置到系统化管理
Nginx 基础架构:从安装配置到系统化管理

本专题深入解析Nginx基础架构,涵盖从源码编译与包管理安装,到核心配置文件优化及虚拟主机部署。进一步探讨日志轮转、性能调优、高可用集群构建及自动化运维策略,助力管理员实现从单一服务搭建到企业级系统化管理的全面升级,确保Web服务高效、稳定运行。

1

2026.03.17

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
JavaScript 基础加强视频教程
JavaScript 基础加强视频教程

共73课时 | 17.5万人学习

Git工具使用小知识
Git工具使用小知识

共38课时 | 17.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号