Go中以下的值是可寻址的,因此可以被取地址:
- 变量
- 可寻址的结构体的字段
- 可寻址的数组的元素
- 任意切片的元素(无论是可寻址切片或不可寻址切片)
- 指针解引用操作
示例:
package main
func main (){
x := struct {a [5]int}{}
// 所有的变量都可寻址
_ = &x
// 若结构体可寻址, 则其字段也可寻址
_ = &x.a
// 若一个数组可寻址, 则其元素也可寻址
_ = &x.a[1]
// 函数的的返回值不可寻址
f := func () []int{ return x.a[:]}
_ = &f() //error
//不可寻址的切片元素总是可以寻址
p:= &f()[1]
// 解引用表达式是可寻址的
_ = &*p
_ = &*&*&*&*&*p
}
Go中以下的值是不可寻址的:
- 字符串的字节元素
- 映射元素
- 接口值的动态值(类型断言的结果)
- 常量值
- 字面值 (如:1, "hello wrold")
- 声明的包级别函数
- 方法(用做函数值)
- 表达式中间结果值
- 数据通道接收操作
- 子字符串操作
- 子切片操作
- 加法、减法、乘法、以及除法等等。
- 函数调用
- 显式值转换
- 各种操作,不包含指针解引用(dereference)操作,但是包含数据通道接收操作、子字符串操作、子切片操作,以及加法/减法/乘法/除法等等。
虽然字面值是不可寻址的,但是组合字面值T{}可以被取地址(虽然它是不可寻址的),这只是为了编程方便而设计的一个语法糖,并非为以上规则的特例。比如下面这段代码编译时没问题的。
示例:
package main
func main (){
_ = &[3]int{1,2,3}
_ = &[]int{1,2,3}
_ = &map[string]int{"Go": 2012}
_ = &struct{}{}
}