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

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

Convert **T to *unsafe.Pointer in Go

问题

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

下面的示例将导致编译错误:

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

  1. package main
  2. import (
  3. "sync/atomic"
  4. "unsafe"
  5. )
  6. type s struct {
  7. value int
  8. }
  9. func main(){
  10. var ptr *s
  11. a := &s{42}
  12. old := ptr
  13. atomic.CompareAndSwapPointer(
  14. (*unsafe.Pointer)(&ptr), // &unsafe.Pointer(ptr)
  15. unsafe.Pointer(old),
  16. unsafe.Pointer(a))
  17. }

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

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

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

编辑

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

  1. up := unsafe.Pointer(ptr)
  2. 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

  1. package main
  2. import (
  3. "sync/atomic"
  4. "unsafe"
  5. )
  6. type s struct {
  7. value int
  8. }
  9. func main(){
  10. var ptr *s
  11. a := &s{42}
  12. old := ptr
  13. atomic.CompareAndSwapPointer(
  14. (*unsafe.Pointer)(&ptr), // &unsafe.Pointer(ptr)
  15. unsafe.Pointer(old),
  16. unsafe.Pointer(a))
  17. }

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:

  1. up := unsafe.Pointer(ptr)
  2. 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提供了一个可行的示例(在此得到了许可):

  1. package main
  2. import (
  3. "fmt"
  4. "sync/atomic"
  5. "unsafe"
  6. )
  7. type T struct {
  8. value int
  9. }
  10. func Swap(dest **T, old, new *T) bool {
  11. udest := (*unsafe.Pointer)(unsafe.Pointer(dest))
  12. return atomic.CompareAndSwapPointer(udest,
  13. unsafe.Pointer(old),
  14. unsafe.Pointer(new),
  15. )
  16. }
  17. func main() {
  18. x := &T{42}
  19. n := &T{50}
  20. fmt.Println(*x, *n)
  21. p := x
  22. Swap(&x, p, n)
  23. fmt.Println(*x, *n)
  24. }
英文:

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

  1. package main
  2. import (
  3. "fmt"
  4. "sync/atomic"
  5. "unsafe"
  6. )
  7. type T struct {
  8. value int
  9. }
  10. func Swap(dest **T, old, new *T) bool {
  11. udest := (*unsafe.Pointer)(unsafe.Pointer(dest))
  12. return atomic.CompareAndSwapPointer(udest,
  13. unsafe.Pointer(old),
  14. unsafe.Pointer(new),
  15. )
  16. }
  17. func main() {
  18. x := &T{42}
  19. n := &T{50}
  20. fmt.Println(*x, *n)
  21. p := x
  22. Swap(&x, p, n)
  23. fmt.Println(*x, *n)
  24. }

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:

确定