go中用&获取变量地址,仅限可寻址值(如变量、结构体字段、切片元素);不可对字面量、map值等取址;指针声明用类型,解引用用p;new(t)返回零值指针,&t{}支持初始化;传指针进函数需*p=修改才影响原变量。

怎么用 & 拿到变量的内存地址
Go 里获取变量地址只有一种方式:& 取址操作符,它返回一个指向该变量的指针。注意:只能对「可寻址」的值取地址,比如普通变量、结构体字段、切片元素;不能对字面量、函数调用结果、常量或 map 的 value 直接取地址。
常见错误现象:cannot take the address of ... —— 比如写 &"hello" 或 &m["key"],Go 编译器会直接报错。
-
&x是合法的,只要x是声明过的变量(如var x int) - 数组元素、切片索引项可取地址:
&s[0]✅,但&s是取整个切片头的地址(不是底层数组),要小心 - map value 不可取地址:
m := map[string]int{"a": 1}; &m["a"]❌,必须先赋给临时变量再取址
指针变量声明和解引用用 * 怎么写才不翻车
* 在类型位置是“指针类型声明”,在表达式位置是“解引用”——这两个语义完全不同,但符号一样,容易混淆。
使用场景:想修改原变量、避免大结构体拷贝、实现可变参数或回调传参时,需要显式声明指针类型并解引用。
立即学习“go语言免费学习笔记(深入)”;
- 声明:
var p *int表示p是一个指向int的指针;p := &x是更常见的初始化方式 - 解引用:
*p = 42修改x的值;fmt.Println(*p)打印x当前值 - 误用典型:
*p := 42是语法错误;var p *int = 42类型不匹配(不能把整数赋给指针变量)
为什么 new() 和 &T{} 都能拿到指针,但行为不同
两者都返回指针,但初始化逻辑和适用场景有本质区别:前者只做零值分配,后者支持字段初始化,且语义更明确。
性能 / 兼容性影响:无实质差异,底层都是堆/栈分配(由逃逸分析决定),但可读性和维护性差别很大。
-
new(T)返回*T,内容是T的零值(如new(int)→&0);不能用于带字段初始化的结构体 -
&T{f: v}更常用,支持字段名初始化、混合字段顺序、省略部分字段(自动补零);例如&struct{a,b int}{a: 1} - 不要混用:
new([]int)返回*[]int(即指向切片头的指针),但通常你想要的是&[]int{1,2}或直接用[]int{1,2}
传指针进函数后,哪些修改能影响原变量
只有通过解引用(*p = ...)修改指针所指向的内存,才能影响原始变量;单纯给指针变量重新赋值(p = &y),不影响调用方的指针值。
常见错误现象:函数内做了 p = &someLocalVar,以为外部变量也被改了,其实只是改了形参副本。
- 能生效:
func f(p *int) { *p = 99 }→ 原变量值被改 - 不生效:
func f(p *int) { x := 99; p = &x }→ 外部指针仍指向原来的地方,且x还可能已逃逸或被回收 - 结构体字段修改也需解引用:
(*s).Name = "foo"或等价的s.Name = "foo"(Go 允许隐式解引用)
最容易被忽略的是:指针本身是值传递,它的“指向关系”不会自动同步回 caller;真正共享的是它指向的那块内存。别指望靠改指针变量来改变 caller 的指针目标。










