3

データを任意に保持するために使用できるvoid*データフィールドを持つ構造体を持つCライブラリをラップしています。これを慣用的なGoでラップするための最良の方法は(可能であれば)何でしょうか?

構造体は非常に単純です:

typedef struct _Foo {
    void * data;
} Foo;

私は次のようなことをしたいと思っていました:

type Foo C.Foo

func (f *Foo) SetData(data interface{}) {
    f.data = unsafe.Pointer(&data)
}

func (f *Foo) Data() interface{} {
    return (interface{})(unsafe.Pointer(f.data))
}

これは機能せず、とにかく明らかに間違ったアプローチです。

[] byteソースを使用して長さフィールドでvoid*データを正常に設定しましたが、この長さのないインターフェイスではわかりません。

4

2 に答える 2

3

のアドレスを取得する場合は、インターフェイスによって「ボックス化」されたデータではなく、interface値型(大まかに)のアドレスを取得します。struct { tInfo *typeInfo, payload uintPtr}ペイロードフィールドは、実際のデータがマハネワードに収まる場合は実際のデータを保持できます。そうでない場合、そのフィールドは実際のペイロードへのポインタを保持します。ただし、これらは実装の詳細であり、IMOと直接連携しないでください。

私は(テストされていないコード、スキーマのみ)のように非ジェネリックになります:

func (f *Foo) SetT(p *T) {
        (*C.Foo)(f).data = unsafe.Pointer(p)
}

func (f *Foo) GetT() *T {
        return (*T)((*C.Foo)(f).data)
}
于 2013-03-11T13:35:54.377 に答える
2

Go under myベルトを数か月続けた後、これに戻って、次の(更新された、ありがとうzupa)ソリューションを思いつきました。

func (f *Foo) SetData(data interface{}) {
    f.data = unsafe.Pointer(&data)
}

func (f *Foo) Data() interface{} {
    return unsafe.Pointer(f.data)
}

また、次のように使用できます。

type Player struct {
    Name string
}

p := &Player{
    Name: "Player1",
}

f.SetData(p)

log.Print(f.Data().(*Player).Name) // Outputs: Player1
于 2013-12-28T14:26:33.973 に答える