You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:33:34