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

huangapple go评论87阅读模式
英文:

Convert **T to *unsafe.Pointer in 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))
}

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

无法获取unsafe.Pointer(ptr)的地址

附:我选择使用sync/atomic进行示例,因为这是一种实际需要进行此类转换的情况。

编辑

一个错误的解决方案是使用临时变量:

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

虽然它可以编译,但CAS只会交换存储在up中的内容,而不是ptr中的内容。这不是期望的结果,正如zeebo@#go-nuts所指出的。

英文:

How do I convert a variable of type **T to *unsafe.Pointer?

The example below will give the compilation error:
> cannot convert &ptr (type **s) to 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))
}

If I switch (*unsafe.Pointer)(&ptr) to &unsafe.Pointer(ptr), I will get this compilation error:
> cannot take the address of unsafe.Pointer(ptr)

Ps. I choose to make an example with sync/atomic because that is one situation where you actually have to do such a conversion.

Edit

One incorrect solution would be to use a temporary variable:

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

While it compiles, the CAS will only swap what is stored in up and not in ptr. This is not the desired result, as zeebo@#go-nuts pointed out.

答案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)
}
英文:

mcef@#go-nuts posted the answer how to convert **T:
> (*unsafe.Pointer)(unsafe.Pointer(ptr)), where ptr is of type **T.

zeebo@#go-nuts provided a working example (posted here with permission):

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

huangapple
  • 本文由 发表于 2012年8月15日 05:07:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/11960743.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定