调用动态类型的接口方法



我正在尝试使用Go接口编写一个通用模块。这会导致一个错误:

panic: interface conversion: interface {} is main.AmazonOrder, not main.OrderMapper

代码:

package main
type AmazonOrder struct {
OrderId string
ASIN string
}
func (o AmazonOrder) Generalise() *Order {
return &Order{
ChannelOrderId: o.OrderId,
}
}
type EbayOrder struct {
OrderId string
SKU string
}
func (o EbayOrder) Generalise() *Order {
return &Order{
ChannelOrderId: o.OrderId,
}
}
type Order struct {
ID string
ChannelOrderId string
}
type OrderMapper struct {
Generalise func() *Order
}
var orderFactory = map[string]func() interface{} {
"amazon": func() interface{} {
return AmazonOrder{}
},
"ebay": func() interface{} {
return EbayOrder{}
},
"vanilla": func() interface{} {
return Order{}
},
}
func main() {
orderType := "amazon"
initialiseOrder := orderFactory[orderType]
anOrder := initialiseOrder()
// Unmarshal from json into anOrder etc.. here.
theOrder := anOrder.(OrderMapper).Generalise()
println(theOrder.ChannelOrderId)
}

在显而易见的逻辑中,这应该可以正常工作。但是,我肯定误解了Go中的类型转换。TIA来澄清它是什么

游乐场:https://play.golang.org/p/tHCzKGzEloL

你必须使用接口,而不是带函数字段的结构体,我在恒河周围留下了注释。

// OrderMapper is probably ment to be an interface. You can convert interface
// to struct only if its the original one. Though you need to convert it into iterface in 
// your case because type of return value is variable. As all orders implement 
// 'Generalise' and you are planing to convert empty interface to OderMapper why not just 
// return order mapper right away? also best practice to name your interface, with just 
// one method, is methodName + 'er' so Generalizer.
type OrderMapper interface {
Generalise() *Order
}
/* alternative
var orderFactory = map[string]func() OrderMapper{
"amazon": func() OrderMapper {
return AmazonOrder{OrderId: "amazonOrderID"}
},
"ebay": func() OrderMapper {
return EbayOrder{}
},
"vanilla": func() OrderMapper {
return Order{}
},
}
*/
var orderFactory = map[string]func() interface{}{
"amazon": func() interface{} {
return AmazonOrder{OrderId: "amazonOrderID"} // i added a value to verify correctness
},
"ebay": func() interface{} {
return EbayOrder{}
},
"vanilla": func() interface{} {
return Order{}
},
}
func main() {
orderType := "amazon"
initialiseOrder := orderFactory[orderType]
anOrder := initialiseOrder()
// Unmarshal from json into anOrder etc.. here.
// alternative: theOrder := anOrder.Generalise()
theOrder := anOrder.(OrderMapper).Generalise()
println(theOrder.ChannelOrderId == "amazonOrderID") // true
}

最新更新