2016-04-06 8 views
2

は、私はこのようになります機能があります。ゴーは:インターフェース{}ポインタを経由して戻り値を渡す

func Foo(result interface{}) error { 
    ... 
    json.Unmarshal([]byte(some_string), result) 
    ... 
} 

このように呼ばれている。一般的に

var bar Bar 
Foo(&bar) 

を、Fooの文字列をフェッチそれは結果にアンマーシャルされます。しかし、Fooが別のソースからデータをロードし、代わりにそのデータを返すように、更新する必要があります。

type Loader func() (interface{}) 

func Foo(result interface{}, Loader load) error { 
    ... 
    data := load() 
    // result = data ??? 
    ... 
} 

結果にこの新しい値を割り当てる方法はありますか?私はデータを文字列に整列化し、それを非整列化して結果として得られることがわかったが、それが最善の方法であるとは想像できない。あなたが行うことができます

+0

からタイプのスイッチを参照してください。結果へのポインタではなく、結果を非整列化します。 'json.Unmarshal([]バイト(some_string)、結果)'。 –

答えて

5

p := result.(*Bar) 
*p = data 

最初の行はtype assertionです。

2番目のポインタは、逆参照ポインタにdataを割り当てます。参照されていないポインタに値を代入すると、参照先のアドレスの値が変更されます。

resultまたはdataの基本タイプがわからないので、できることはタイプアサーションスイッチを使用することです。

switch v := data.(type) { 
case Bar: 
    // If 'data' is of type 'Bar' 
    p, ok := result.(*Bar) 
    if(!ok){ 
     // This means inputs were bad. 
     // 'result' and 'data' should both have the same underlying type. 
     fmt.Println("underlying types mismatch") 
     break; 
    } 

    *p = v 

case Baz: 
    // If 'data' is of type 'Baz' 
    // Equivalent of above for 'Baz' 
} 

はFooの最初のバージョンは動作しませんswitch statement

+0

Foo内の具体的な結果の種類がわからないという問題のみです。だからこそ私は{}を使用しています。それを理解するためにリフレクションを使用する必要がありますか? – Bill

+0

ビル、残念私はそれを見落とした。私が思いつく最高のソリューションで答えを更新しました。私はあなたがこのAPIを使用して考えていることを願っています。たぶんポインタを割り当てる代わりにデータを返すように変更することはできますか? –

+0

どのようにリファクタリングしても、デシリアライズケースの参照先構造体を渡す必要があります。私はいつも構造体をロードしているか、または文字列を逆シリアル化しているところまでいつも行きます。これは、foo(result interface {}、load Loader)(インタフェース{}、エラー)のようなものです。 – Bill

関連する問題