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

聖光之護

聖光之護

2025-07-14

411人浏览

原创

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_ 结构体实例的内存地址。

《H5与HTML之前版本的区别》
《H5与HTML之前版本的区别》

《H5与HTML之前版本的区别》

下载
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 语言中结构体的使用。

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

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

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

2023.10.31

1214

5

php数据类型
php数据类型

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

2025.10.31

388

9

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

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

2026.02.12

298

19

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

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

2025.06.09

2050

18

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

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

2025.07.04

1845

25

C++ 智能指针与现代内存管理
C++ 智能指针与现代内存管理

深入讲解 C++ 现代内存管理的核心工具——智能指针,涵盖 unique_ptr 独占所有权语义、shared_ptr 引用计数机制与循环引用问题、weak_ptr 弱引用的应用场景、make_unique/make_shared 工厂函数的性能优势、自定义删除器的编写、RAII 资源管理思想的实践,以及从裸指针迁移到智能指针的重构策略,帮助开发者编写安全无泄漏的现代 C++ 代码。

2026.04.23

114

31

火山引擎API Key获取教程
火山引擎API Key获取教程

火山引擎API Key适合需要调用火山引擎云服务、AI模型、火山方舟接口或其他开放能力的开发者参考。本专题整理控制台入口、账号认证、服务开通、API Key创建、密钥复制保存、权限检查、调用测试和Key无效等常见问题排查。

2026.08.04

0

10

火山引擎API接入教程
火山引擎API接入教程

火山引擎API接入适合需要在应用、脚本、后台服务或AI工具中调用火山引擎能力的开发者参考。本专题整理控制台入口、服务开通、API Key获取、接口地址配置、请求参数填写、调用测试、权限设置、额度查询和常见接口报错排查。

2026.08.04

0

10

火山引擎DeepSeek API调用教程
火山引擎DeepSeek API调用教程

火山引擎DeepSeek API适合需要在应用、脚本、智能体或AI编程工具中调用DeepSeek模型的开发者参考。本专题整理火山引擎控制台入口、模型服务开通、API Key获取、Base URL配置、模型名称填写、调用测试、额度查询和常见接口报错排查。

2026.08.04

0

10

热门下载

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

精品课程

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

共73课时 | 19.4万人学习

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

共38课时 | 18.7万人学习