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{}{}
}