尝试在切片指针上进行测距时,我一直收到此错误。
app/domain/repositories/class_repository.go:24: cannot range over classes (type *[]entities.Class)
我做错了什么?
这是结构:
package repositories
import (
"mobifit/app/domain/entities"
)
type ClassRepository struct {
*Repository
}
func (c *ClassRepository) ClassesForLastNDays(days int) *[]entities.Class {
classes := new([]entities.Class)
query := Select("*").
From("Class").
Where("VisibleAt > CURRENT_TIMESTAMP() - INTERVAL ? DAY").
OrderBy("ClassTypeId").
Sql()
c.Repository.Select(classes, query, days)
c.populateClassRelationships(classes)
return classes
}
func (c *ClassRepository) populateClassRelationships(classes *[]entities.Class) {
for i := range classes { <<<<<<<<<<< Here is the problem
class := classes[i]
// ClassType
c.Repository.GetById(class.ClassType, class.ClassTypeId)
//Instructor
c.Repository.GetById(class.Instructor, class.ClassType.InstructorId)
// Equipment
query := Select("E.*").
From("Equipment E").
Join("ClassEquipment CE on E.Id = CE.EquipmentId").
Where("CE.ClassId = ?").
Sql()
c.Repository.Select(class.Equipment, query, class.Id)
}
}
这是Class结构:
package entities
import (
"time"
)
type Class struct {
Id int
ClassTypeId int
VideoPath string
VideoSize int
Duration float64
CreatedAt time.Time
VisibleAt time.Time
NoLongerVisibleAt time.Time
// Relationships
ClassType ClassType
Instructor User
Equipment []Equipment
}
答案 0 :(得分:21)
您假设指向切片的指针将自动解除引用以进行迭代。
情况并非如此,并且没有理由这样做,因为切片已经是一种指针,渲染指向切片的指针完全没用。
来自Effective Go:
如果函数采用切片参数,则更改它对元素的影响 对于调用者来说,切片是可见的,类似于传递一个 指向底层数组的指针。
在内部,切片由
组成此结构非常小,导致指针无效。
答案 1 :(得分:8)
来自Effective Go:
如果您循环遍历数组,切片,字符串或地图或阅读 通过一个通道,一个范围子句可以管理循环。
您正在尝试将指针迭代到一个单独的切片,而不是一个集合因此是不可能的。
将参数更改为populateClassRelationships
为切片,而不是指向切片的指针。或者您可以取消引用指针:
func (c *ClassRepository) populateClassRelationships(classes *[]entities.Class) {
for i := range *classes { // dereferencing the pointer to get the actual slice
class := classes[i]
// ClassType
c.Repository.GetById(class.ClassType, class.ClassTypeId)
//Instructor
c.Repository.GetById(class.Instructor, class.ClassType.InstructorId)
// Equipment
query := Select("E.*").
From("Equipment E").
Join("ClassEquipment CE on E.Id = CE.EquipmentId").
Where("CE.ClassId = ?").
Sql()
c.Repository.Select(class.Equipment, query, class.Id)
}
}
答案 2 :(得分:6)
如果您需要从*切片中提取单个元素,则必须首先取消引用它:(*slice)[0]
。在我意识到这一点之前,我对*slice[0]
约了6个小时。它与操作的顺序有关,而不是,IMO,这是一个非常优雅的结果。
我最后编写了一些指针接收器方法来进行就地修改,比如追加和弹出更多,在我看来,合理的方式 - 可以在这里找到一个例子:https://play.golang.org/p/qZEYMcPHl4
答案 3 :(得分:5)
您可以取消引用指针:
func (c *ClassRepository) populateClassRelationships(classes *[]entities.Class) {
for _, class := range *classes { // NOTE the * dereference
// ClassType
c.Repository.GetById(class.ClassType, class.ClassTypeId)
//Instructor
c.Repository.GetById(class.Instructor, class.ClassType.InstructorId)
// Equipment
query := Select("E.*").
From("Equipment E").
Join("ClassEquipment CE on E.Id = CE.EquipmentId").
Where("CE.ClassId = ?").
Sql()
c.Repository.Select(class.Equipment, query, class.Id)
}
}
我也改变了范围子句,因为我认为你不是在修改classes
。