我有一个接口Model,它是由 struct 实现的Person。5 e3 l6 D# k, I2 y
为了获得模型实例,我有以下帮助函数:. q2 Y g3 @% l4 s' U% J0 d+ ?
func newModel(c string) Model switch c case "person": return newPerson() return nil}func newPerson() *Person return &erson{}} 6 u& E: i. `* [, E! g }
上述方法允许我返回正确类型的 Person 实例(以后可以用同样的方法轻松添加新模型)。 ) _ T+ d# Y# V; I2 [当我试图执行类似的操作返回模型切片时,会出现错误。/ V6 o- H. d9 |+ w- Z x: F9 R
func newModels(c string) []Model switch c case "person": return newPersons() return nil}func newPersons() *[]Person var models []Person return &models} & U$ r( i+ K. y6 l
去抱怨: cannot use newPersons() (type []Person) as type []Model in return argument ! _+ r9 [0 X3 d4 l! ]7 h我的目标是返回请求的任何模型切片(无论是[]Person、[]FutureModel、[]Terminator2000、 w/e)。我错过了什么,如何正确实施这样的解决方案?2 x6 Q: \: `" R c, B, f- o$ h
' K4 G% F" F7 \1 Z解决方案: I; i( H' b* P# Y( V" z
简短的答案是你是对的。结构切片不等于结构实现接口切片。5 a. }% y' k- h6 h3 Y4 I# i
A[]Person和 a[]Model内存布局不同。这是因为它们的切片类型有不同的内存布局。AModel它是一个接口值,这意味着它在内存中的大小是两个字。一个词表示类型信息,另一个词表示数据。APerson它的大小取决于它包含的字段。a 转换[]Person为 a []Model,您需要遍历数组并转换每个元素的类型。4 U! u0 A/ N. {( F% t1 h1 l
因为这个转换是一个 O(n) 操作并且会导致一个新的切片被创建,Go 拒绝隐式这样做。您可以使用以下代码显式执行此操作。7 u0 I( B# m) V/ P% _( T$ F
models := make([]Model,len(persons))for i,v := range persons models = Model(v)}return models! i$ U1 H+ B/ t2 u