Go语言中两种指针创建方式的行为差异及原理咨询
指针两种创建方式的区别及Go代码行为解析
首先来明确你问的两种指针使用方式的核心差异:
一、a := &A; a vs b := B; &b 的区别
a := &A:这里的&A是直接获取A的内存地址。如果A是字面量(比如&data{1}),Go会为这个字面量分配一块内存(具体在栈还是堆上由Go的逃逸分析决定),a作为指针变量指向这块内存。后续如果给a重新赋值(比如a = &A2),a会指向全新的内存块,和原来的地址完全无关。b := B; &b:先创建一个命名变量b(通常分配在栈上),&b获取的是这个变量b本身的固定内存地址。不管后续怎么修改b的值,这个地址都不会变——所有指向&b的指针,都会同步看到b的最新值。
二、你的Go代码行为拆解
我们逐行分析这段代码里d1和d2的不同表现:
package main import "fmt" type data struct { value int } func main() { m := make(map[string]*data) // --- d1 的流程 --- d1 := &data{1} // 1. 创建匿名的data{1}实例,d1是指向它的指针 m["d1"] = d1 // 2. map里存入的是「指向data{1}的指针」 d1 = &data{2} // 3. d1现在指向一个全新的data{2}实例,和之前的data{1}无关联 fmt.Println(m["d1"]) // 输出&{1} —— map里存的还是原来的指针,指向旧实例 // --- d2 的流程 --- d2 := data{1} // 1. 在栈上创建命名变量d2,初始值为data{1} m["d2"] = &d2 // 2. map里存入的是「变量d2的内存地址」 d2 = data{2} // 3. 修改d2变量本身的值(内存地址不变,仅value字段更新为2) fmt.Println(m["d2"]) // 输出&{2} —— map里的指针始终指向d2的地址,自然看到最新值 }
核心总结
- 用
&data{1}创建指针时,你得到的是指向独立实例的指针——后续重新赋值指针变量,只会切换指针指向的实例,不会影响已存入map的旧指针。 - 先创建命名变量再取地址
&d2时,你得到的是指向该变量的固定地址——变量的值可以修改,所有指向这个地址的指针都会同步看到变化。
内容的提问来源于stack exchange,提问作者Shahriar
相关产品推荐
相关产品推荐

