1

次の作業を行い、出力を作成するにはどうすればよい"Result is: [Value from GetFromMemory]."ですか?

残念ながら、 と のメソッド シグネチャを変更することはできませGetItemGet

http://play.golang.org/p/R5me3Q3y4W

package main

import "fmt"

type Key string

type Item struct {
    Key   Key
    Value string
}

func GetItem(key Key) interface{} {
    return &Item{key, "Value from GetFromMemory"}
}

// How can I make item point to the one created in GetItem?
func Get(key Key, item interface{}) {
    item = GetItem(key)
}

func main() {
    var item Item
    Get("Key1", &item)

    // This should print "Result is: [Value from GetFromMemory]."
    fmt.Printf("Result is: [%s].", item.Value)
}
4

1 に答える 1

9

interface{}値を扱っているので、型アサーションまたはリフレクションが必要です。

扱うタイプがわかっている場合は、おそらくタイプ アサーションが適しています ( Code on play )。

func GetItem(key Key) interface{} {
    return &Item{key, "Value from GetFromMemory"}
}

func Get(key Key, item interface{}) {
    switch v := item.(type) {
        case **Item:
            *v = GetItem(key).(*Item)
    }
}

// Usage:
var item *Item
Get("Key1", &item)

のコードは、Getさらにいくつかのタイプの条件を簡単に追加できるようにレイアウトされています。タイプ スイッチは、の基になるタイプをチェックしますitem。この場合、これは an へのポインタへのポインタですItem(これは*Itemmain にGetあり、 のアドレスを指定し&itemて、 にしました**Item)。

タイプが一致する場合に一致するセクションで、 を呼び出しGetItem、結果のオブジェクトがタイプであることをアサートし、*Itemそれを にコピーでき*vます。

でポインター値を生成しているため、item変数をに変更したことに注意してください。そのため、オブジェクトのコピーではなくポインターを取得する方が理にかなっています。*ItemGetItemItem

から値を取得するために使用されるような型アサーションの結果を確認する必要があることにも注意してくださいGetItem。そうしないと、タイプが一致しない場合、たとえば 、*Itemコードは実行時パニックで爆発します。

確認済みの型アサーション:

v, ok := someInterfaceValue.(SomeType)
// ok will be true if the assertion succeeded

完全を期すために、リフレクションでも問題を解決できます。次のように定義Getします ( play の例):

func Get(key Key, item interface{}) {
    itemp := reflect.ValueOf(item).Elem()
    itemp.Set(reflect.ValueOf(GetItem(key)))
}

何が起こるかというと、最初にitem(type **Item) の反映された値が逆参照され、それがポインター値であると想定され、type の反映された値が得られ*Itemます。この値はGetItem、メソッドを使用しての反映された値で設定されますSet

もちろん、種類itemが実際にポインターであるかどうかを確認する必要があります。これを行わずにポインタ以外の値を渡すとGet、パニックが発生します。

于 2013-10-20T00:43:25.867 に答える