结构切片!=它实现的接口切片? [英] slice of struct != slice of interface it implements?
问题描述
我有一个接口Model
,由struct Person
实现.
I have an interface Model
, which is implemented by struct Person
.
为了获得模型实例,我有以下辅助函数:
To get a model instance, I have the following helper functions:
func newModel(c string) Model {
switch c {
case "person":
return newPerson()
}
return nil
}
func newPerson() *Person {
return &Person{}
}
上述方法允许我返回一个正确类型的 Person 实例(稍后可以使用相同的方法轻松添加新模型).
The above approach allows me to return a properly typed Person instance (can easily add new models later with same approach).
当我尝试为返回模型切片执行类似操作时,出现错误.代码:
When I attempted to do something similar for returning a slice of models, I get an error. Code:
func newModels(c string) []Model {
switch c {
case "person":
return newPersons()
}
return nil
}
func newPersons() *[]Person {
var models []Person
return &models
}
Go 抱怨:cannot use newPersons() (type []Person) as type []Model in return argument
我的目标是返回请求的任何模型类型的切片(无论是[]Person
、[]FutureModel
、[]Terminator2000
, 我们).我错过了什么,我该如何正确实施这样的解决方案?
My goal is to return a slice of whatever model type is requested (whether []Person
, []FutureModel
, []Terminator2000
, w/e). What am I missing, and how can I properly implement such a solution?
推荐答案
这和我刚刚回答的一个问题非常相似:https://stackoverflow.com/a/12990540/727643
This is very similar to a question I just answered: https://stackoverflow.com/a/12990540/727643
简短的回答是你是对的.结构的切片不等于结构实现的接口的切片.
The short answer is that you are correct. A slice of structs is not equal to a slice of an interface the struct implements.
[]Person
和 []Model
具有不同的内存布局.这是因为它们切片的类型具有不同的内存布局.Model
是一个接口值,这意味着在内存中它的大小是两个字.一个词表示类型信息,另一个词表示数据.Person
是一个结构体,其大小取决于它包含的字段.为了从 []Person
转换为 []Model
,您需要遍历数组并对每个元素进行类型转换.
A []Person
and a []Model
have different memory layouts. This is because the types they are slices of have different memory layouts. A Model
is an interface value which means that in memory it is two words in size. One word for the type information, the other for the data. A Person
is a struct whose size depends on the fields it contains. In order to convert from a []Person
to a []Model
, you will need to loop over the array and do a type conversion for each element.
由于这个转换是一个 O(n) 操作并且会导致一个新的切片被创建,Go 拒绝隐式这样做.您可以使用以下代码显式执行此操作.
Since this conversion is an O(n) operation and would result in a new slice being created, Go refuses to do it implicitly. You can do it explicitly with the following code.
models := make([]Model, len(persons))
for i, v := range persons {
models[i] = Model(v)
}
return models
正如 dskinner 指出的,您很可能需要一个指针切片,而不是指向切片的指针.通常不需要指向切片的指针.
And as dskinner pointed out, you most likely want a slice of pointers and not a pointer to a slice. A pointer to a slice is not normally needed.
*[]Person // pointer to slice
[]*Person // slice of pointers
这篇关于结构切片!=它实现的接口切片?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!