3

次のように定義されたインターフェースのペアがあります。

type Marshaler interface {
    Marshal() ([]byte, error)
}

type Unmarshaler interface {
    Unmarshal([]byte) error
}

これらを実装する単純なタイプがあります:

type Foo struct{}

func (f *Foo) Marshal() ([]byte, error) {
    return json.Marshal(f)
}

func (f *Foo) Unmarshal(data []byte) error {
    return json.Unmarshal(data, &f)
}

別のインターフェイスを定義するライブラリを使用しており、次のように実装しています。

func FromDb(target interface{}) { ... }

渡される値targetは、ポインターへのポインターです。

fmt.Println("%T\n", target) // Prints **main.Foo

通常、この関数は型の切り替えを行い、その下の型で動作します。インターフェイスを実装するすべての型に共通のコードが必要ですUnmarshalerが、特定の型のポインター ツー ポインターからインターフェイスへの取得方法がわかりません。

ポインターへのポインターでメソッドを定義することはできません。

func (f **Foo) Unmarshal(data []byte) error {
    return json.Unmarshal(data, f)
}
// compile error: invalid receiver type **Foo (*Foo is an unnamed type)

ポインター型でレシーバー メソッドを定義することはできません。

type FooPtr *Foo

func (f *FooPtr) Unmarshal(data []byte) error {
    return json.Unmarshal(data, f)
}
// compile error: invalid receiver type FooPtr (FooPtr is a pointer type)

キャストがUnmarshaler機能しない:

x := target.(Unmarshaler)
// panic: interface conversion: **main.Foo is not main.Unmarshaler: missing method Unmarshal

へのキャストも*Unmarshaler機能しません:

x := target.(*Unmarshaler)
// panic: interface conversion: interface is **main.Foo, not *main.Unmarshaler

このポインタからポインタへの型からインターフェイス型に、考えられるすべての実装型をオンにする必要なく、どのように取得できますか?

4

2 に答える 2

2

が で、が実装されている場合targetは、次のことができます。**Foo*FooUnmarshaler

var x Unmarshaler = *target

target が a をinterface{}含むan の場合**Foo、代わりに次のように動作します。

var x Unmarshaler = *(target.(**Foo))

タイプスイッチがある場合も同様の考えです。

ポインターからポインターへ、またはポインターから参照へのポインターを処理する必要がある場合は常に、変数の有効期間は一般的にかなり短く、すぐに単一のポインター (または単純な参照) に戻ります。

当面のユースケースにポインターツーポインターが実際に必要かどうか、またはそのようなことができるかどうかを評価します。

于 2013-09-04T17:15:03.560 に答える