6

タイプの変数を に変換するにはどうすればよい**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) のアドレスを取得できません

Ps。sync/atomic実際にそのような変換を行う必要がある状況の 1 つであるため、例を作成することにしました。

編集

間違った解決策の 1 つは、一時変数を使用することです。

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 に答える