1

如何进行以下工作并进行输出"Result is: [Value from GetFromMemory]."

不幸的是,我无法更改 和 的方法GetItem签名Get

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{}值时,您需要类型断言或反射。

如果您知道要处理哪些类型,则类型断言可能是您的最佳选择(代码在玩):

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(它*Item在 main 中,然后我们给出Get了 的地址&item,使其成为 a **Item)。

在类型匹配时匹配的部分中,我们可以调用GetItem,断言结果对象是类型*Item并将其复制到*v

请注意,当您在 中生成指针值时,我将item变量更改为,因此获取指针而不是对象的副本更有意义。*ItemGetItemItem

另请注意,您需要检查类型断言的结果,例如用于从GetItem. 如果您不这样做并且类型不匹配,例如*Item,您的代码将因运行时恐慌而崩溃。

检查类型断言:

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

为了完整起见,您也可以通过反射解决您的问题。定义Get如下(播放示例):

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

发生的情况是,首先item(type **Item) 的反射值被取消引用,假设它是一个指针值,给我们一个 type 的反射值*ItemGetItem然后通过使用该Set方法将所述值设置为反射值。

当然,您需要检查类型是否item实际上是指针。不这样做并将非指针值传递给Get将导致恐慌。

于 2013-10-20T00:43:25.867 回答