在Go中将**T转换为*unsafe.Pointer

ANi*_*sus 5 pointers type-conversion unsafe-pointers go

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

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

无法将&ptr(类型**s)转换为*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))
}
Run Code Online (Sandbox Code Playgroud)

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

不能取不安全的地址.Pointer(ptr)

PS.我选择做一个例子,sync/atomic因为这是你必须进行这种转换的一种情况.

编辑

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

up := unsafe.Pointer(ptr)
atomic.CompareAndSwapPointer(&up, ...
Run Code Online (Sandbox Code Playgroud)

在编译时,CAS只会交换存储的内容up而不是内存中的内容ptr.这不是理想的结果,正如zeebo @#go-nuts所指出的那样.

ANi*_*sus 6

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)
}
Run Code Online (Sandbox Code Playgroud)

  • 如果“T”实际上是一个接口而不是“结构”,你会怎么做? (2认同)