回答

收藏

结构切片!=它实现的接口切片?

技术问答 技术问答 233 人阅读 | 0 人回复 | 2023-09-12

我有一个接口Model,它是由 struct 实现的Person。- R* [2 Z! k5 G6 j9 `0 k7 t; w
为了获得模型实例,我有以下帮助函数:/ l; w; g: p; o5 g2 r& U  v' K
    func newModel(c string) Model    switch c    case "person":        return newPerson()      return nil}func newPerson() *Person    return &erson{}}1 j4 x8 a' x4 T7 {5 _
上述方法允许我返回正确类型的 Person 实例(以后可以用同样的方法轻松添加新模型)。
* L" E5 r( L- y4 W$ m% e当我试图执行类似的操作返回模型切片时,会出现错误。
) m- z* Y8 p' ?" i2 f
    func newModels(c string) []Model    switch c    case "person":        return newPersons()      return nil}func newPersons() *[]Person    var models []Person    return &models}
    4 r8 e6 Z% [0 m
去抱怨: cannot use newPersons() (type []Person) as type []Model in return argument/ p6 }, e3 N0 V' \  {
我的目标是返回请求的任何模型切片(无论是[]Person、[]FutureModel、[]Terminator2000、 w/e)。我错过了什么,如何正确实施这样的解决方案?5 I1 I5 z  q: T7 ]! ]) R3 ~6 l
                                                                5 k7 d) ?: y7 a) L2 Y/ s0 {
    解决方案:                                                               
4 X5 n) z, ~8 _* J                                                                简短的答案是你是对的。结构切片不等于结构实现接口切片。# W3 c" w9 ~7 V8 p
A[]Person和 a[]Model内存布局不同。这是因为它们的切片类型有不同的内存布局。AModel它是一个接口值,这意味着它在内存中的大小是两个字。一个词表示类型信息,另一个词表示数据。APerson它的大小取决于它包含的字段。a 转换[]Person为 a []Model,您需要遍历数组并转换每个元素的类型。  v' M2 k& r! U
因为这个转换是一个 O(n) 操作并且会导致一个新的切片被创建,Go 拒绝隐式这样做。您可以使用以下代码显式执行此操作。
: v" g" C# S5 a4 c& I) s8 d4 M: {( C
    models := make([]Model,len(persons))for i,v := range persons    models = Model(v)}return models
    & h# K) z2 t# J/ R; a
正如ner 指出,你可能需要指针切片,而不是指针切片。通常不需要指向切片的指针。5 h$ W2 {) y6 z
    *[]Person     pointer to slice[]*Person     slice of pointers6 x# b6 M3 X% V; j4 \" L
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则