golang:它的结构片!=它实现的接口片?
我有一个接口Model ,由struct Person实现。 
为了得到一个模型实例,我有以下的帮助函数:
 func newModel(c string) Model { switch c { case "person": return newPerson() } return nil } func newPerson() *Person { return &Person{} } 
上面的方法允许我返回一个正确types的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 
 我的目标是返回一个任何模型types的请求(无论是[]Person , []FutureModel , []Terminator2000 ,w / e)的[]FutureModel 。 我错过了什么,如何正确实施这样的解决scheme? 
这与我刚刚回答的问题非常相似: https : //stackoverflow.com/a/12990540/727643
简短的回答是,你是正确的。 结构的一部分不等于结构实现的接口的一部分。
  A []Person和[]Model具有不同的内存布局。 这是因为它们的切片types具有不同的内存布局。  Model是一个界面值,这意味着在内存中它是两个字的大小。 一个字为types信息,另一个为数据。  Person是一个结构,它的大小取决于它所包含的字段。 为了从[]Person转换为[]Model ,您将需要遍历数组并为每个元素进行types转换。 
由于这个转换是一个O(n)操作,并且会导致一个新的slice被创build,所以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 
 也许这是你的返回types*[]Person ,它应该实际上是[]*Person以便引用该片的每个索引是对Person的引用,并且其中slice []本身就是一个引用到一个数组。 
看看下面的例子:
 package main import ( "fmt" ) type Model interface { Name() string } type Person struct {} func (p *Person) Name() string { return "Me" } func NewPersons() (models []*Person) { return models } func main() { var p Model p = new(Person) fmt.Println(p.Name()) arr := NewPersons() arr = append(arr, new(Person)) fmt.Println(arr[0].Name()) } 
正如斯蒂芬已经回答了这个问题,你是一个初学者,我强调给予build议。
使用go的接口的一个更好的方法是不要有一个构造函数像其他语言(比如java)那样返回接口,而是要独立地为每个对象构造一个构造函数,因为它们隐含地实现了接口。
代替
 newModel(type string) Model { ... } 
你应该做
 newPerson() *Person { ... } newPolitician() *Politician { ... } 
 与人和Politician都实施Model的方法。 您仍然可以在Model被接受的任何地方使用Person或Politician ,但是您也可以实现其他接口。 
 使用你的方法,你将被限制为Model直到你手动转换到另一个接口types。 
 假设我有一个实现了Walk()方法的Person和一个Model实现了ShowOff() ,下面的代码不会直接工作: 
 newModel("person").ShowOff() newModel("person").Walk() // Does not compile, Model has no method Walk 
但是,这将会:
 newPerson().ShowOff() newPerson().Walk() 
typesT和[] T是不同的types,不同的是他们的方法,即使在满足相同的接口。 IOW中,每个满足模型的types必须自己实现所有模型的方法 – 方法接收器可以只有一个特定的types。
正如其他人已经回答,[T]是一个独特的types。 我只想补充一点,一个简单的实用程序可以用来一般地转换它们。
 import "reflect" // Convert a slice or array of a specific type to array of interface{} func ToIntf(s interface{}) []interface{} { v := reflect.ValueOf(s) // There is no need to check, we want to panic if it's not slice or array intf := make([]interface{}, v.Len()) for i := 0; i < v.Len(); i++ { intf[i] = v.Index(i).Interface() } return intf } 
现在,你可以像这样使用它:
 ToIntf([]int{1,2,3})