如何获得一个接口{}参数指向别的东西?

时间:2013-10-20 00:09:27

标签: google-app-engine go

如何进行以下工作并输出"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)
}

1 个答案:

答案 0 :(得分: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。< / p>

在匹配类型匹配的部分中,我们可以调用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的反射值。说过 然后使用GetItem方法将值设置为Set的反射值。

当然,您需要检查item的类型是否实际上是指针。 不执行此操作并将非指针值传递给Get将导致恐慌。