如何进行以下工作并输出"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)
}
答案 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
将导致恐慌。