小编典典

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

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
}

去抱怨: cannot use newPersons() (type []Person) as type []Model in return argument

我的目标是返回请求的任何模型类型的切片(无论是[]Person[]FutureModel[]Terminator2000、 w/e)。我错过了什么,我该如何正确实施这样的解决方案?


阅读 168

收藏
2021-12-24

共1个答案

小编典典

简短的回答是你是对的。结构的切片不等于结构实现的接口的切片。

A[]Person和 a[]Model具有不同的内存布局。这是因为它们切片的类型具有不同的内存布局。AModel是一个接口值,这意味着在内存中它的大小是两个字。一个词表示类型信息,另一个词表示数据。APerson是一个结构体,其大小取决于它包含的字段。为了从 a 转换[]Person为 a []Model,您需要遍历数组并对每个元素进行类型转换。

由于这个转换是一个 O(n) 操作并且会导致一个新的切片被创建,Go 拒绝隐式地这样做。您可以使用以下代码显式执行此操作。

models := make([]Model, len(persons))
for i, v := range persons {
    models[i] = Model(v)
}
return models

正如ner 指出的那样,您很可能需要一个指针切片,而不是指向切片的指针。通常不需要指向切片的指针。

*[]Person        // pointer to slice
[]*Person        // slice of pointers
2021-12-24