6

如何将类型变量转换**T*unsafe.Pointer?

下面的示例将给出编译错误:

无法将 &ptr (type **s) 转换为 type *unsafe.Pointer

package main

import (
    "sync/atomic"
    "unsafe"
)

type s struct {
    value int
}

func main(){
    var ptr *s
    a := &s{42}

    old := ptr
    atomic.CompareAndSwapPointer(
        (*unsafe.Pointer)(&ptr), // &unsafe.Pointer(ptr)
        unsafe.Pointer(old),
        unsafe.Pointer(a))
}

如果我切换(*unsafe.Pointer)(&ptr)&unsafe.Pointer(ptr),我会得到这个编译错误:

不能取 unsafe.Pointer(ptr) 的地址

附言。我选择做一个例子,sync/atomic因为这是你实际上必须进行这种转换的一种情况。

编辑

一种不正确的解决方案是使用临时变量:

up := unsafe.Pointer(ptr)
atomic.CompareAndSwapPointer(&up, ...

在编译时,CAS 只会交换存储在up而不是ptr. 正如 zeebo@#go-nuts 所指出的,这不是预期的结果。

4

1 回答 1

7

mcef@#go-nuts 发布了如何转换 **T 的答案:

(*unsafe.Pointer)(unsafe.Pointer(ptr)),其中 ptr 的类型为 **T。

zeebo@#go-nuts 提供了一个工作示例(经许可在此处发布):

package main

import (
    "fmt"
    "sync/atomic"
    "unsafe"
)

type T struct {
    value int
}

func Swap(dest **T, old, new *T) bool {
    udest := (*unsafe.Pointer)(unsafe.Pointer(dest))
    return atomic.CompareAndSwapPointer(udest,
        unsafe.Pointer(old),
        unsafe.Pointer(new),
    )
}

func main() {
    x := &T{42}
    n := &T{50}
    fmt.Println(*x, *n)

    p := x
    Swap(&x, p, n)
    fmt.Println(*x, *n)
}
于 2012-08-14T22:14:34.683 回答