在 Go 语言里,什么样的值可以被取地址,什么样的值不能取地址?请给出具体规则和例子。
考察说明
考查对 Go 语言可寻址性概念及其与语言特性关联的理解。
回答思路
- 【回答框架 1】可寻址的包括:变量、数组元素、切片元素、指针指向的值、map 的 value 字段(但 map 本身不可寻址,且如果 value 是结构体,其字段不可直接取地址)、结构体可寻址变量的字段。
- 【回答框架 2】不可寻址的包括:常量、字符串中的字节、切片字面量(如 []int{1})、map 字面量、函数返回值(即使返回的是指针,指针本身不可寻址)、表达式结果(如 a+b)、类型转换结果、包装后的接口值。
- 【回答框架 3】判断依据:Go 中可寻址的值必须能通过 & 操作得到地址,且该地址指向的内存是持久可变的。临时值(如函数返回值)在求值后销毁,不可取地址。此外,range 循环变量在每次迭代中复用,Go 1.22 后循环变量是每迭代独立变量,可寻址。
- 【回答框架 4】应用影响:不可寻址值不能作为需要指针参数的函数实参,也不能用 & 对它们取地址。常见陷阱包括对 map value 字段取地址、对函数返回值取地址。
- 【回答框架 5】结合语言特性:可寻址性与赋值、方法调用(自动取地址)相关。只有可寻址的变量才能调用指针接收者方法。
- 【关键点 1】变量、数组元素、切片元素、指针指向的值是典型可寻址。
- 【关键点 2】常量、字符串元素、map 元素、函数返回值、表达式结果不可寻址。
- 【关键点 3】map 的 value 不可寻址,即使 value 是结构体,其字段也不可寻址。
- 【关键点 4】对不可寻址值取地址会编译错误,可寻址性影响方法调用和指针参数传递。
- 【易错点 1】区分 map 元素本身不可寻址,但 map 的键和值可以通过赋值更新。
- 【易错点 2】切片元素可寻址,但切片字面量不可寻址,因为字面量是临时值。
- 【易错点 3】结构体字面量(如 Foo{})不可寻址,除非赋值给变量。