回答

收藏

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

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

我有一个接口Model,它是由 struct 实现的Person。- S' K4 z0 g0 z& I; e2 f
为了获得模型实例,我有以下帮助函数:
2 w5 M, a  E$ S, H; |+ j
    func newModel(c string) Model    switch c    case "person":        return newPerson()      return nil}func newPerson() *Person    return &erson{}}4 t, k, r' w& ^0 c9 y7 W
上述方法允许我返回正确类型的 Person 实例(以后可以用同样的方法轻松添加新模型)。2 m2 W# j' S' U
当我试图执行类似的操作返回模型切片时,会出现错误。1 y- K; c! d9 o1 |; x
    func newModels(c string) []Model    switch c    case "person":        return newPersons()      return nil}func newPersons() *[]Person    var models []Person    return &models}3 f; V% ^  I+ }4 H
去抱怨: cannot use newPersons() (type []Person) as type []Model in return argument' s; c, \3 Z0 q8 {, A1 Q8 O5 P0 x' _
我的目标是返回请求的任何模型切片(无论是[]Person、[]FutureModel、[]Terminator2000、 w/e)。我错过了什么,如何正确实施这样的解决方案?2 D/ m- i0 ?' R, t& b
                                                               
( d1 C, a* c2 z- X" s    解决方案:                                                               
* A# w2 ]) U0 X9 x                                                                简短的答案是你是对的。结构切片不等于结构实现接口切片。, a+ }; I! c& y0 Z) Y2 B# T
A[]Person和 a[]Model内存布局不同。这是因为它们的切片类型有不同的内存布局。AModel它是一个接口值,这意味着它在内存中的大小是两个字。一个词表示类型信息,另一个词表示数据。APerson它的大小取决于它包含的字段。a 转换[]Person为 a []Model,您需要遍历数组并转换每个元素的类型。( T4 j1 _# `& O+ U1 z
因为这个转换是一个 O(n) 操作并且会导致一个新的切片被创建,Go 拒绝隐式这样做。您可以使用以下代码显式执行此操作。
4 G- Y8 t( K# I' ]+ @$ V! f6 j
    models := make([]Model,len(persons))for i,v := range persons    models = Model(v)}return models7 S- D& W$ f5 _8 K. L% W8 f( S; V
正如ner 指出,你可能需要指针切片,而不是指针切片。通常不需要指向切片的指针。
% u$ C" ^' A" w7 H' \- f& \6 L7 e
    *[]Person     pointer to slice[]*Person     slice of pointers
    ! u4 U/ L6 P* P6 C- I3 X
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则