一开始,我想给大家介绍一下,因为我觉得我缺少一些Golang的核心概念。
在我的应用中,很多模型都会有一个叫做GetByUserId的方法。我创建了需要这个方法的接口(UserCreatedEntity),这样我就可以为每种类型的记录创建Controller的GetUserRecords方法工厂。
router.Handle("/ideas/mine",
middlewares.AuthUser(controllers.GetMineFactory(&models.Idea{}))).Methods("POST")
router.Handle("/votes/mine",
middlewares.AuthUser(controllers.GetMineFactory(&models.Vote{}))).Methods("POST")
router.Handle("/someNewType/mine",
middlewares.AuthUser(controllers.GetMineFactory(&models.SomeNewType{}))).Methods("POST")
这是我的接口的样子:
type UserCreatedEntity interface {
GetByUserId(userId uint) []UserCreatedEntity
}
和实现。
func (idea *Idea) GetByUserId(userId uint) []UserCreatedEntity {
ideas := []Idea{}
GetDB().
Table("ideas").
/** Query removed to make code less confusing **/
Scan(ideas)
return ideas
}
很明显,这是不工作的(有指针片的版本也不工作)。问题是--如果我只返回一条记录,这段代码就会工作--就像这样(很明显,在接口中也改变了签名)。
func (idea *Idea) GetByUserId(userId uint) UserCreatedEntity {
idea := &Idea{}
GetDB().
Table("ideas").
/** Query removed to make code less confusing **/
First(idea)
return idea
}
如何让它像slice一样工作?正如我所说,我怀疑我缺少一些重要的知识。所以,深入的解释将是真棒。
解决办法。
func (idea *Idea) GetByUserId(userId uint) []UserCreatedEntity {
ideas := []*Idea{}
GetDB().
Table("ideas").
Select("problems.name AS problem_name, ideas.id, ideas.problem_id, ideas.action_description, ideas.results_description, ideas.money_price, ideas.time_price, ideas.is_published").
Joins("INNER JOIN problems ON ideas.problem_id = problems.id").
Where("ideas.user_id = ?", userId).
Scan(&ideas)
uces := make([]UserCreatedEntity, len(ideas))
for i, idea := range ideas {
uces[i] = idea
}
return uces
}
接口是动态的。涉及接口的复合类型不是。
UserCreatedEntity
是一个接口,而 Idea
满足接口,所以你可以返回一个 Idea
的函数,其签名的返回类型为 UserCreatedEntity
.
[]UserCreatedEntity
是一片 UserCreatedEntity
,而不是一个接口。唯一可以返回的类型是 []UserCreatedEntity
. []Idea
是一种不同的类型(片的 Idea
). 你可以填写一个 []UserCreatedEntity
与 Idea
元素,因为每个元素都是类型为 UserCreatedEntity
,这也是一个接口和 Idea
是允许的。
同样地: func() UserCreatedEntity
是一个类型 "函数,它返回 UserCreatedEntity
". 你不能用"。func() Idea
因为那是一个不同的类型。但你可以返回一个 Idea
从 func() UserCreatedEntity
因为 Idea
是一个 UserCreatedEntity
.
如果你没有使用 Scan
这里,它可能使用反射,修复方法是将你的本地片断声明为 []UserCreatedEntity
而不是 []Idea
. 由于您使用的是 Scan
而您必须扫描到一个 []Idea
然后在它上面遍历,把所有的元素复制到一个叫做 []UserCreatedEntity
并将其返回。