2013-10-20 20 views
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) 
} 
+0

也許GetItem應該返回一個* Item?也許Get應該返回一個接口{}而不是更新一個傳入的變量? –

+0

@匿名OP明確表示他不能更改這兩個函數的簽名。這可能是因爲它們是[GAE數據存儲區API](https://developers.google.com/appengine/docs/go/datastore/reference#Get)的一部分。 – nemo

+0

這完全正確@nemo。我試圖用[Gorilla Context API](http://www.gorillatoolkit)與[GAE Datastore API](https://developers.google.com/appengine/docs/go/datastore/reference#Get)結婚。 org/pkg/context#Get),以便在轉到數據存儲之前檢查結構的內存。 – Dan

回答

9

當你正在處理interface{}值,你要麼需要type assertions或反射。

如果你知道你會處理類型,類型的斷言很可能去 (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的代碼佈局,使您可以輕鬆地添加更多的條件更多 類型。 type switch檢查底層類型item。在這種情況下,它是一個 指針指向一個Item(它主要是*Item,然後我們給了Get地址&item,使它成爲**Item)。

在相匹配的類型相匹配時,節中,我們可以調用GetItem,斷言導致對象是*Item類型,並將其複製到*v

注意,我改變了item變量*Item爲你製作的GetItem指針值,所以它更有意義得到的指針,而不是一個Item對象的副本。

另外請注意,您需要檢查類型斷言喜歡用來 檢索GetItem價值的一個結果。如果你沒有和類型不匹配,說,*Item, 你的代碼將爆炸與運行時恐慌。

經過類型斷言:

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

爲了完整起見,你可以解決您反映的問題,以及。 定義Get如下(Example on play):

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

什麼情況是,在第一item(類型**Item)的反射值被廢棄時, 假設它是一個指針值,使我們有類型的反射值*Item。然後通過使用Set方法將 值與反射值GetItem一起設置。

當然,您需要檢查item是否實際上是一個指針。 不這樣做,並傳遞一個非指針值到Get將導致恐慌。

+1

謝謝@nemo!這正是我所期待的,我從你的綜合答案中學到了很多,所以謝謝!事實上,我冒昧地生產了這些例子,而沒有爲其他人使用雙指針的額外間接。請參閱http://play.golang.org/p/cRqqgkjuFX的'''switch'''代碼和http://play.golang.org/p/ubiq_7uev2反射代碼。 – Dan

相關問題