详细介绍:Go 语言中指针介绍
指针是 Go 语言中一个非常核心的概念,也是许多从 PHP 等高级语言转过来的开发者最需要适应的一个点。不过别担心,Go 的指针比 C/C++ 中的指针要安全和简单得多。
理解指针的关键在于,它能让你在程序的不同部分共享和修改同一份数据,而不是传来传去的数据副本。
我们同样从简单到高阶,分场景来彻底搞懂它。
核心概念:什么是指针?
在探讨场景前,我们必须先建立一个清晰的心理模型。
想象一下,一个变量 v
就像一座房子 ,里面住着数据(比如数字 10
)。
- 变量
v
本身代表房子,可以直接访问里面的数据。 - 指针
p
则是写着这座房子地址的一张纸条 。
指针(Pointer)本身也是一个变量,但它存储的不是普通数据,而是另一个变量的内存地址。
Go 提供了两个核心操作符来使用指针:
&
(取地址符): 当用在变量前面时(如&v
),它的意思是“给我这座房子的地址”。*
(解引用符): 当用在指针变量前面时(如*p
),它的意思是“去纸条上写的地址,把那座房子里的东西取出来”。它也用在类型声明中,表示一个指针类型(如*int
表示一个指向整数的指针)。
场景一:基础且最常见的用法
1. 在函数中修改外部变量
这是你学习指针的首要理由,也是我们之前在“方法”部分遇到的指针接收者的原理。
- 场景: 你需要写一个函数,这个函数要能修改传入的参数的值,而不是修改一个副本。例如,一个函数需要将外部的一个计数器加一。
- 用法:
a) 错误示范 (值传递)
b) 正确示范 (指针传递)func addOne_Fail(num int) { num = num + 1 // 这里修改的是 num 的一个副本 } func main() { x := 5 addOne_Fail(x) fmt.Println(x) // 输出仍然是 5,原始的 x 没有被改变 }
我们之前学的// 参数是一个指向 int 的指针 func addOne_Success(num *int) { // *num 的意思是“去 num 这个地址,把里面的值取出来” // 然后对这个值进行修改 *num = *num + 1 } func main() { x := 5 // &x 的意思是“把 x 的地址传进去” addOne_Success(&x) fmt.Println(x) // 输出是 6,原始的 x 被成功修改了! }
func (u *User) HaveBirthday()
就是这个原理。u
接收的是User
实例的地址,所以方法能修改原始的User
。
场景二:中阶/性能考量
2. 避免大数据结构的值拷贝
当你的结构体非常大时,在函数间以“值传递”的方式传来传去,会产生巨大的性能开销。因为每一次函数调用,Go 都需要完整地复制一遍整个结构体。
- 场景:
- 你有一个包含大量字段的配置结构体
Config
,需要把它传递给多个函数去读取其中的不同部分。 - 你有一个包含大数据块(比如一个图片或一段音频)的结构体。
- 你有一个包含大量字段的配置结构体
- 用法: 通过传递结构体的指针,你实际上只复制了一个非常小的内存地址(通常是 8 字节),而不是整个庞大的结构体数据。
经验法则:当你的结构体比较大,或者需要在多处共享和修改时,优先使用指针。type BigStruct struct { // 假设这里有很多字段,占用很大内存 data [1024 * 10]byte // 10KB 的数据 } // 低效的方式:每次调用都会复制 10KB 的数据 func processByValue(s BigStruct) { /* ... */ } // 高效的方式:只复制一个 8 字节的指针 func processByPointer(s *BigStruct) { /* ... */ } func main() { data := BigStruct{} processByPointer(&data) // 这是更推荐的做法 }
场景三:高阶/地道用法
3. 表示“可选”或“缺失”的值
一个指针的零值是 nil
。这个特性非常有用,可以用来区分“一个值为零”和“根本没有提供值”这两种情况。
- 场景: 你在设计一个用于更新用户信息的 API。用户只想更新他的年龄,而不想改动姓名。如果你的更新结构体是
struct { Name string; Age int }
,那么传过来的 JSON{"age": 30}
会导致Name
字段是空字符串""
。你是要更新用户的姓名为空,还是用户根本没提供姓名?这就有歧义了。 - 用法: 将结构体字段定义为指针类型。如果 JSON 中没有这个字段,那么指针的值就是
nil
。
输出会是:type UpdateUserPayload struct { Name *string `json:"name,omitempty"` Age *int `json:"age,omitempty"` } func main() { // 假设只收到了 age 字段 jsonStr := `{"age": 31}` var payload UpdateUserPayload json.Unmarshal([]byte(jsonStr), &payload) if payload.Name != nil { fmt.Println("用户想要更新姓名为:", *payload.Name) } else { fmt.Println("用户没有提供新的姓名。") } if payload.Age != nil { fmt.Println("用户想要更新年龄为:", *payload.Age) } else { fmt.Println("用户没有提供新的年龄。") } }
通过检查指针是否为用户没有提供新的姓名。 用户想要更新年龄为: 31
nil
,我们就能准确地知道用户到底想更新哪些字段。
4. 构建链式数据结构
像链表、树这样的数据结构,其节点之间就是通过指针连接起来的。
- 场景: 实现一个链表或二叉树。
- 用法: 结构体中包含一个或多个指向同类型结构体的指针。
nil
指针自然地表示链表的末尾或树的叶子节点。type Node struct { Value int Next *Node // 指向下一个节点的指针 } func main() { node1 := Node{Value: 10} node2 := Node{Value: 20} node1.Next = &node2 // node1 的 Next 指针指向 node2 的地址 // 这样,node1 和 node2 就连接起来了 fmt.Println(node1.Value) // 10 fmt.Println(node1.Next.Value) // 通过指针访问下一个节点的值: 20 }
总结
对于有 PHP 背景的你来说,可以这样简单理解:
- 当你需要在函数或方法内部修改外部的变量时,使用指针。
- 当你传递一个很大的结构体,想避免复制开销时,使用指针。
- 当你需要表达一个值**“可能不存在”**时,使用指针。
Go 的指针是一个强大但清晰的工具,它让你能更精确地控制程序的内存和数据流。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/936785.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!相关文章
实用指南:JavaWeb 课堂笔记 —— 24 AOP 面向切面编程
实用指南:JavaWeb 课堂笔记 —— 24 AOP 面向切面编程pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas&q…
2025年7款与Jira数据同步的实用国产优秀项目管理软件对比
为什么我们需要这篇对比?
如果你是一位项目经理,或许经历过这些困扰:团队用惯了Jira,但因数据合规要求急需国产替代,却担心同步成本高、功能断层?
想找一款能与Jira无缝对接的工具,兼顾本地化服务与灵活扩展,却…
ESP8266 PMW使用的简单介绍
前言
呼吸灯是常见的LED应用。LED呼吸灯的流程是缓缓点亮LED灯,再缓缓熄灭LED灯。在夜色下,缓慢闪烁的LED显得格外迷人。 如何使用ESP8266MOD实现此效果, 这里简单地总结一下。
一、PWM单元介绍ESP8266有四个PWM输出…
DevEco Testing全面解析:HarmonyOS测试框架与实战指南 - 教程
DevEco Testing全面解析:HarmonyOS测试框架与实战指南 - 教程pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Con…
C#知识学习-015(修饰符_4) - 详解
C#知识学习-015(修饰符_4) - 详解pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco…
加州新规要求AI必须表明其AI身份
加州通过SB 243法案,要求伴侣聊天机器人必须明确告知用户其AI身份,并建立自杀预防报告机制。该法案旨在保护儿童安全,要求AI开发者实施防护措施,防止用户误以为在与真人交流。加州新规要求AI必须表明其AI身份
一项…
详细介绍:【rabbitmq 高级特性】全面详解RabbitMQ TTL (Time To Live)
详细介绍:【rabbitmq 高级特性】全面详解RabbitMQ TTL (Time To Live)pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: &…
第三台中转机实现远程scp文件到远程
点击查看代码
命令
scp -3r user@ip:/path/file user@ip:/path/ 远程主机(源)-》中转机-》远程主机(目标)如果要实现免密需要
ssh-copy-id user@ip 将本地的 SSH 公钥快速复制到远程主机的 ~/.ssh/authorized_key…
单片机使用同一硬件定时器实现多周期定时功能
一个复杂的单片机程序可能需要很多种周期不同的定时器,用于执行不同的任务,如传感器数据采集、显示设备刷新或者执行设备的驱动等。如果每种周期使用一个单片机的硬件定时器将很难实现全部的功能需求,本文记录一种简…
(二十六)、Kuboard 部署网络问题 k8s 使用本地镜像 k8s使用 register本地镜像站 综合应用 - 实践
(二十六)、Kuboard 部署网络问题 &k8s 使用本地镜像 & k8s使用 register本地镜像站 综合应用 - 实践pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; displa…
低代码平台底层协议设计
低代码平台底层协议设计
1. 核心协议架构
1.1 协议分层设计
// 低代码平台协议栈
interface LowCodeProtocolStack {// 1. 传输层协议transport: TransportProtocol;// 2. 数据描述协议schema: SchemaProtocol;// 3. 组…
从PHP到Spring Boot:思维的转变与入门实战 (指南二) - 教程
从PHP到Spring Boot:思维的转变与入门实战 (指南二) - 教程2025-10-14 12:27
tlnshuju
阅读(0)
评论(0) 收藏
举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !impor…
Vue 低代码平台渲染引擎设计
Vue 低代码平台渲染引擎设计
1. 核心架构设计
1.1 整体架构
// 渲染引擎核心接口定义
interface RenderEngine {schema: PageSchema; // 页面Schemacomponents: ComponentMap; // 组件映射dataSource: D…
微前端架构:实战指南与未来趋势 - 详解
pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …
基于海思Hi3798MV200 Android7.0达成电影播放蓝光导航功能
基于海思Hi3798MV200 Android7.0达成电影播放蓝光导航功能pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consola…
2025 年热处理钎焊炉工装夹具厂家推荐榜:钎焊炉用耐热钢工装夹具厂家,聚焦品质与适配,助力企业高效生产
随着制造业对热处理工艺精度要求的不断提升、设备耐用性需求增强及生产标准化推进,热处理钎焊炉工装夹具已从高端冶金、核工业领域逐步拓展至石油、化工、电力、矿山等多个行业,2025 年市场规模预计持续增长。但市场…
实用指南:基于Spring Boot与SSM的社团管理系统架构设计
实用指南:基于Spring Boot与SSM的社团管理系统架构设计pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas&…
完整教程:数据结构 01 线性表
pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …