1.7 指针
    支持指针类型 *T,指针的指针 *T,以及包含包名前缀的 .T

    • 默认值 nil,没有 NULL 常量。
    • 操作符 “&” 取变量地址,”*” 透过指针访问目标对象。
    • 不支持指针运算,不支持 “->” 运算符,直接用 “.” 访问目标成员。
      1. func main() {
      2. type data struct{ a int }
      3. var d = data{1234}
      4. var p *data
      5. p = &d
      6. fmt.Printf("%p, %v\n", p, p.a)
      7. // 直接用指针访问目标对象成员,无须转换。
      8. }
      9. // 输出: 0x2101ef018, 1234

    不能对指针做加减法等运算。

    1. x := 1234
    2. p := &x
    3. p++ // Error: invalid operation: p += 1 (mismatched types *int and int)

    可以在 unsafe.Pointer 和任意类型指针间进行转换。

    1. func main() {
    2. x:= 0x12345678
    3. p:= unsafe.Pointer(&x) // *int -> Pointer
    4. n := (*[4]byte)(p) // Pointer -> *[4]byte
    5. for i := 0; i < len(n); i++ {
    6. fmt.Printf("%X ", n[i])
    7. }
    8. }
    9. //输出: 78 56 34 12

    返回局部变量指针是安全的,编译器会根据需要将其分配在 GC Heap 上。

    1. func test() *int {
    2. x := 100
    3. return &x // 在堆上分配 x 内存。但在内联时,也可能直接分配在目标栈。
    4. }

    Pointer 转换成 uintptr,可变相实现指针运算。

    1. func main() {
    2. d := struct {
    3. s string
    4. x int
    5. }{"abc", 100}
    6. p := uintptr(unsafe.Pointer(&d)) // *struct -> Pointer -> uintptr
    7. p += unsafe.Offsetof(d.x) // uintptr + offset
    8. p2 := unsafe.Pointer(p) // uintptr -> Pointer
    9. px := (*int)(p2) // Pointer -> *int
    10. *px = 200 // d.x = 200
    11. fmt.Printf("%#v\n", d)
    12. }
    13. // 输出:
    14. struct { s string; x int }{s:"abc", x:200}

    注意:GC 把 uintptr 当成普通整数对象,它无法阻止 “关联” 对象被回收。