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

深度解读Go 变量指针

在Go语言中,指针是一个存储变量内存地址的变量。通过指针,可以间接访问和操作原始数据。从而提高程序的效率,特别是在处理复杂数据结构或需要共享数据时。

概念说明
指针声明var p *int
取地址&a → 获取 a 的地址
解引用*p → 访问 p 指向的值
零值nil
主要用途修改变量、避免拷贝、动态分配

1. 指针的本质

  • 指针是一种特殊变量,其值是另一个变量的内存地址
  • 通过指针可以间接访问或修改原始变量的值。

2. 声明指针

语法:var ptr *Type

var a int = 10
var ptr *int // 声明一个指向 int 类型的指针
ptr = &a     // 将 a 的内存地址赋值给 ptr

3. 关键操作符

  • &(取地址符):获取变量的内存地址。
  ptr = &a // ptr 现在存储 a 的地址
  • *(解引用符):访问指针指向的原始值。
  fmt.Println(*ptr) // 输出 10(通过 ptr 访问 a 的值)*ptr = 20         // 修改 a 的值为 20

4. 指针的零值

  • 未初始化的指针值为 nil(表示无指向)。
  var ptr *int // 初始值为 nil

5. 指针的用途

  • 修改函数外部的变量
  func modify(val *int) {*val = 100}func main() {x := 10modify(&x) // x 被修改为 100}
  • 避免大对象拷贝:传递结构体指针而非整个结构体,减少内存开销。
  type Data struct { /* 大结构体 */ }func process(d *Data) { /* 操作 d */ }
  • 动态内存分配:与 new 或复合字面量一起使用。
  p := new(int) // 分配内存,返回指针*p = 42

6. 指针示例

package mainimport "fmt"func main() {a := 10ptr := &a      // ptr 指向 afmt.Println("a 的值:", a)         // 10fmt.Println("a 的地址:", &a)       // 0xc00001a0a0fmt.Println("ptr 的值:", ptr)      // 0xc00001a0a0(与 &a 相同)fmt.Println("ptr 指向的值:", *ptr) // 10*ptr = 20      // 通过指针修改 afmt.Println("a 的新值:", a) // 20
}

7. 注意!!!!!!!

  • 空指针(nil):解引用 nil 指针会导致运行时 panic。
  • 指针算术:Go 不支持指针算术(如 ptr++),除非使用 unsafe 包(不推荐)。
  • 值传递 vs 指针传递函数参数默认值传递,需用指针实现引用传递。

扩展:使用指针修改原始变量和通过函数修改的区别是什么

原理差异

  • 指针修改:在 Go 里,字符串是不可变类型,若要通过指针修改字符串,实际上修改的是存储字符串的字节切片。因为字符串底层由字节数组构成,借助指针操作可改变字节切片内容,再转换回字符串,从而更新原始变量。
  • strings.Builder 修改strings.Builder 内部维护一个字节切片,提供方法将字符串追加到该切片。当调用 String 方法时,会把内部字节切片转换为字符串返回。这种方式不会直接修改原始字符串,而是生成新字符串后重新赋值给原始变量。

代码实现差异

指针修改示例

package mainimport ("fmt"
)func modifyString(s *string) {bytes := []byte(*s)bytes = append(bytes, ' ', 'a', 'b', 'c')*s = string(bytes)
}func main() {str := "this is a string"fmt.Println(&str)modifyString(&str)fmt.Println(str)
}

strings.Builder 修改示例

package mainimport ("fmt""strings"
)func main() {str := "this is a string"fmt.Println(&str)// 创建一个 strings.Builder 实例var builder strings.Builder// 将原始字符串写入 Builderbuilder.WriteString(str)// 在末尾添加 abcbuilder.WriteString(" abc")// 获取最终的字符串str = builder.String()fmt.Println(str)
}

性能差异

  • 指针修改:每次修改都要将字符串转换为字节切片,修改后再转换回字符串,频繁转换会带来额外内存分配和复制开销,性能欠佳。
  • strings.Builder 修改:内部维护字节切片,可动态扩容,减少内存分配次数,拼接字符串时性能更优,尤其在处理大量字符串拼接时优势明显。

使用场景差异

  • 指针修改:适用于需要直接操作原始变量内存地址,且修改操作较少的场景,或者希望通过函数修改外部变量的场景。
  • strings.Builder 修改适合需要频繁进行字符串拼接的场景,能有效提升性能。

http://www.lryc.cn/news/601380.html

相关文章:

  • [每周一更]-(第152期):Go中的CAS(Compare-And-Swap)锁原理详解
  • iOS安全和逆向系列教程 第20篇:Objective-C运行时机制深度解析与Hook技术
  • 结合Golang语言说明对多线程编程以及 select/epoll等网络模型的使用
  • goland编写go语言导入自定义包出现: package xxx is not in GOROOT (/xxx/xxx) 的解决方案
  • 学习Python中Selenium模块的基本用法(1:简介)
  • Day06–哈希表–242. 有效的字母异位词,349. 两个数组的交集,202. 快乐数,1. 两数之和
  • 仓库管理系统-2-后端之基于继承基类的方式实现增删改查
  • 7.25 C/C++蓝桥杯 |排序算法【下】
  • macOS 安装 Homebrew
  • JavaScript事件(event)对象方法与属性
  • mac配置多版本jdk
  • C#中Visual Studio平台按照OfficeOpenXml步骤
  • Min-Max标准化​ 和 ​Z-score标准化
  • Python队列算法:从基础到高并发系统的核心引擎
  • LeetCode|Day27|70. 爬楼梯|Python刷题笔记
  • Spring Retry 异常重试机制:从入门到生产实践
  • Spring Boot自动配置原理深度解析
  • 适配IE11(通过Babel+core-js转译ES6语法)
  • Flutter 生命周期介绍
  • 几个注册中心的特性
  • 欧拉图与欧拉回路
  • 菜鸟的C#学习(四)
  • windows 10安装oracle(win64_11gR2)
  • 医疗AI语义潜空间分析研究:进展与应用
  • Unity 实时 CPU 使用率监控
  • IP--MGER综合实验报告
  • Linux驱动20 --- FFMPEG视频API
  • 回归预测 | MATLAB实现BiTCN双向时间卷积神经网络多输入单输出回归预测
  • AWS免费套餐全面升级:企业降本增效与技术创新解决方案
  • 《频率之光》