Go中&取变量的可寻址位置而非裸地址,仅限局部变量、结构体字段等可寻址值;用于解引用指针,nil解引用会panic;函数传指针需调用方&、形参T、函数内*p配对使用。

Go里&不是取“内存地址”,而是取“变量的可寻址位置”
Go的&操作符返回的是一个指针值,但它不暴露裸地址(比如0x7fffa123),也不允许做指针算术。它只表示“能通过这个指针修改原变量”的绑定关系。只有可寻址的变量才能用&——比如局部变量、结构体字段、切片元素;但不能对字面量、函数调用结果、常量或map键值直接取地址。
-
&42❌ 编译报错:cannot take the address of 42 -
&len(s)❌len()返回的是不可寻址的临时值 -
&s[0]✅ 切片元素可寻址(只要s非nil且索引有效) -
&struct{X int}{1}.X✅ 字面量结构体字段可寻址(Go 1.15+)
*解引用必须作用于指针类型,否则编译失败
*是解引用操作符,只能用于*T类型。它不是“读内存”,而是“访问指针所指向的变量”。如果指针为nil,运行时解引用会panic:invalid memory address or nil pointer dereference。
-
var p *int; *p = 1→ panic,因为p == nil -
var x int; p := &x; *p = 5✅ 正确,x变为5 -
*3❌ 编译错误:invalid indirect of 3 (type int) -
*&x✅ 等价于x,但无实际意义,仅用于演示双向性
函数参数传指针时,&和*要配对出现在调用与定义两侧
Go默认按值传递。想让函数修改原始变量,需显式传指针。这时调用方用&,函数形参声明为*T,函数体内用*写入或读取。
func inc(p *int) {
*p++ // 修改p指向的int
}
func main() {
x := 10
inc(&x) // 这里必须加 &
fmt.Println(x) // 输出11
}
- 漏写
&(如inc(x))→ 类型不匹配:cannot use x (type int) as type *int - 形参写成
int却在函数内*p→ 编译错误:invalid indirect of p (type int) - 传
&someStructField没问题,但别传&someMap["key"],因为map值不可寻址
指针接收者方法中,&和*隐含在调用语法里
定义func (p *T) Method()后,Go允许对T值或*T值调用该方法——编译器自动补&或*。但这只是语法糖,底层仍遵循指针规则。
立即学习“go语言免费学习笔记(深入)”;
-
var t T; t.Method()→ 编译器自动转为(&t).Method() -
var pt *T; pt.Method()→ 直接调用,无需再解引用 - 但如果
Method()内部修改了*p字段,而你用t.Method()调用,改的仍是t的副本字段(除非T本身是指针类型) - 接口值存储
T时,不能调用*T方法;反之亦然——这是常见运行时panic来源
nil检查比语法本身更关键。很多崩溃不是因为写错了&或*,而是没确认目标是否真能被寻址,或者忘了在解引用前判空。









