我有一个有趣的问题。
我想向端点发出请求,该端点在HTTP响应中返回给我一系列对象。
然后,我想将该响应解组为切片结构。很容易。
此代码有效:
type Human struct {}
func (h Human) Talk() {}
type CanTalk interface{
Talk()
}
type Model struct {
List []CanTalk
}
func main() {
model := Model{}
data, err := makeRequestToEndpoint()
if err != nil {
// ...
}
err = json.Unmarshal(data, &model.List)
if err != nil {
// ...
}
for _, human := range model.List {
human.Talk()
}
}
但是这里有个要点:我想一般地这样做。
我不想为系统中的每个单一类型编写相同的逻辑(因为它们都在单独的文件中),所以我选择使用interface{}
而不是[]CanTalk
,这样我就可以将其下的unmarshal和逻辑抽象为一个实用函数。然后为interface{}
注入json.Unmarshal的具体类型。
即使该程序可以编译并运行,它也不起作用:
type Human struct {}
func (h Human) Talk() {}
type CanTalk interface{
Talk()
}
type Model struct {
List interface{} // Using interface{} here instead of []CanTalk
}
func main() {
model := Model{List:[]Human{}} // Seeding the list with the specified type to unmarshal into
data, err := makeRequestToEndpoint()
if err != nil {
// ...
}
err = json.Unmarshal(data, &model.List)
if err != nil {
// ...
}
if list, ok := model.List.([]interface{}); ok {
for i := range list {
// This line is never reached, because "ok == false"
if human, ok := list[i].(CanTalk); ok {
// Never reached
human.Talk()
}
}
}
}
如您所见,元帅不会接我给model.List
的种子。解组后model.List
的输出仍然是HTTP响应有效载荷的格式(map[string]interface{}
或类似的格式),而不是种子的类型,因此无法转换为{{1 }}类型。
这是否有可能,或者实现此目标(缺少真正的泛型)的唯一方法是对系统中每种单独的类型重复解组逻辑?