发布于2026-05-21 阅读(0)
扫一扫,手机访问
聊到Go语言,指针总是一个绕不开的话题。它不像C语言里那样让人望而生畏,但也绝非可以掉以轻心的存在。今天,我们就来把Go指针的那些关键操作、使用场景和注意事项,掰开揉碎了讲清楚。
简单来说,指针就是一个“地址记录员”。它不存储实际的数据,只负责记住另一个变量在内存中的“门牌号”。声明一个指针变量,格式是这样的:

// ptr是指针变量名,*表示是指针类型,*int表示它记录的是一个int类型变量的地址 var ptr *int
用好指针,全靠两个符号:& 和 *。它们就像一把钥匙的正反两面。
| 符号 | 名称 | 作用 | 示例 |
& |
取址符 | 获取变量在内存中的地址,返回指针类型 | ptr := &num (获取 num 的地址) |
* |
解引用符 |
1. 声明时:表示指针类型(如 *int) 2. 使用时:获取或修改指针指向的具体值 |
|
光说不练假把式,来看一段代码,把声明、取址、解引用的流程走一遍:
package main
import "fmt"
func main() {
// 1. 先定义一个普通变量
num := 100
fmt.Printf("普通变量值: %d, 地址: %p\n", num, &num)
// 2. 声明一个指针,并让它指向num的地址
var ptr *int = &num // 现在ptr记住了num住在哪里
// 3. 通过指针“遥控”原始变量
fmt.Printf("指针指向的值: %d\n", *ptr) // 输出 100,读取原值
*ptr = 200 // 修改指针指向的那个内存单元里的值
fmt.Printf("修改后原始变量值: %d\n", num) // 输出 200,原值确实被改了
}
刚声明还没初始化的指针,默认值是nil。你可以把它理解成一个指向“虚无”的指针。
Go语言在底层把nil当作地址为0的特殊值。所以,判断ptr == nil会得到true,打印它的地址会显示0x0。
这里有个大坑: 试图对一个nil指针进行解引用(比如执行*ptr),程序会立刻崩溃,并报错“panic: invalid memory address or nil pointer dereference”。这就好比拿着一个空地址去找房子,结果当然是找不到。
package main
import "fmt"
func main() {
var ptr *int // 未初始化,ptr是nil
if ptr == nil {
fmt.Printf("%p", ptr) // 输出 0x0
}
// *ptr = 5 // 如果执行这行,程序会panic
}
Go语言的函数参数默认是值传递,也就是说,传进去的是个副本。如果你想在函数内部修改外部的那个“原件”,就必须传递指针。
func increment(ptr *int) {
*ptr++ // 直接修改指针指向的那个原始值
}
func main() {
count := 10
increment(&count) // 把count的地址传进去
fmt.Println(count) // 输出 11,原值被成功修改
}
想象一下,你有一个包含成千上万个元素的结构体或数组。如果按值传递,整个数据都会被复制一份,既费内存又耗CPU。传递指针就高效多了,它只复制一个内存地址(在64位系统上就8个字节)。
type BigData struct {
Items [10000]int
}
// 使用指针接收,避免拷贝10000个int的巨大开销
func process(data *BigData) {
// 在这里处理数据
data.Items[0] = 1 // 修改会直接影响外部的原始结构体
}
指针虽好,但用起来也得讲究章法,否则容易踩坑。
不是所有东西都能用&取地址。以下几种情况,编译器会直接报错“cannot take the address of ...”:
&42、&"hello"。数字42和字符串“hello”本身没有固定的内存地址。&m["key"]。因为Map底层结构可能会动态调整,其值的位置不固定,所以禁止直接取址。如果非要用,得先赋值给一个临时变量。这是Go语言设计上的一个巧妙之处。
append导致底层数组换了),或者想替换掉整个Map对象,那还是需要传递指针(如*[]int)。不过这种场景在日常开发中比较少见。int、bool或者很小的结构体这类“轻量级”数据,值传递往往更快。因为指针操作多了一次“寻址”的开销,还可能引发不必要的堆分配。sync/atomic.Pointer:这是为高并发场景准备的“武器”,提供了无锁的原子指针操作,适合做状态切换。unsafe.Pointer:这是一把“双刃剑”。它能让你绕过Go的类型系统,直接进行指针转换,极其危险。它不参与GC的生命周期管理,用不好很容易导致“悬垂指针”(访问已释放内存)或内存破坏。除非你在写底层系统库、驱动或者追求极致性能的框架,否则在业务代码里请远离它。总的来说,Go语言的指针在提供强大能力的同时,也通过语言设计规避了许多传统指针的陷阱。理解它的原理,明确它的适用场景和边界,你就能在需要的时候,游刃有余地使用这个工具。
下一篇:何为java平台?
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8