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所指出的那样.
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)