php小编苹果在这里为大家揭开一个有关结构体切片的谜题:结构体切片与它实现的接口切片之间的差别是什么?在Go语言中,切片是一种方便且灵活的数据结构,可以动态改变大小。而结构体切片则是切片的一种特殊形式,它存储的是结构体类型的元素。但是,它与实现了相同接口的切片之间有何不同呢?让我们一起来揭晓答案。
问题内容
我有一个接口Model
,它是由struct Person
实现的。
为了获取模型实例,我有以下辅助函数:
func newModel(c string) Model {
switch c {
case "person":
return newPerson()
}
return nil
}
func newPerson() *Person {
return &Person{}
}
上述方法允许我返回一个正确类型的 Person 实例(稍后可以使用相同的方法轻松添加新模型)。
当我尝试执行类似的操作来返回模型切片时,出现错误。代码:
func newModels(c string) []Model {
switch c {
case "person":
return newPersons()
}
return nil
}
func newPersons() *[]Person {
var models []Person
return &models
}
Go 抱怨: 无法使用 newPersons()(类型 []Person)作为返回参数中的类型 []Model
我的目标是返回请求的任何模型类型的切片(无论是 []Person
、[]FutureModel
、[]Terminator2000
,w/e)。我缺少什么,如何正确实施这样的解决方案?
解决方法
这与我刚刚回答的问题非常相似:https://www.php.cn/link/2c029952e202c0e560626a4c5980d64c
简短的回答是你是对的。结构体的切片不等于结构体实现的接口的切片。
[]Person
和 []Model
具有不同的内存布局。这是因为它们所属的类型具有不同的内存布局。 Model
是一个接口值,这意味着在内存中它的大小为两个字。一个词代表类型信息,另一个词代表数据。 Person
是一个结构,其大小取决于它包含的字段。为了从 []Person
转换为 []Model
,您需要循环数组并对每个元素进行类型转换。
由于此转换是一个 O(n) 操作并且会导致创建一个新切片,因此 Go 拒绝隐式执行此操作。您可以使用以下代码明确地执行此操作。
models := make([]Model, len(persons))
for i, v := range persons {
models[i] = Model(v)
}
return models
正如 dskinner 指出的,您很可能需要一个指针切片,而不是指向切片的指针。通常不需要指向切片的指针。
*[]Person // pointer to slice
[]*Person // slice of pointers
以上就是结构体切片!=它实现的接口切片?的详细内容,更多请关注编程网其它相关文章!