Golang不能指向切片的指针范围

Lee*_*Lee 22 go

尝试在切片指针上进行测距时,我不断收到此错误.

app/domain/repositories/class_repository.go:24: cannot range over classes (type *[]entities.Class)
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?

这是结构:

 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)
    }
}
Run Code Online (Sandbox Code Playgroud)

这是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
    }
Run Code Online (Sandbox Code Playgroud)

Den*_*ret 23

您假设指向切片的指针将自动解除引用以进行迭代.

事实并非如此,并且没有理由这样做,因为切片已经是一种指针,渲染指向切片的指针完全没用.

Effective Go开始:

如果函数采用切片参数,则对切片元素所做的更改将对调用者可见,类似于将指针传递给基础数组.

在内部,切片由

  • 指向底层数组中切片的第一个元素的指针
  • 切片的长度
  • 切片的容量(切片通常可以延长到数组的末尾)

这种结构非常小,使得指针无用.

  • 澄清:指向切片的指针有一个用途:如果程序的多个部分需要共享同一切片,那么对切片本身的修改将反映在程序的其他部分中(例如,如果从切片中删除元素)通过执行a = append(a [:i],a [i + 1:] ...)应该反映在其他数据结构所持有的切片中).但是,这很少是您想要的,并且在没有锁定的情况下不是线程安全的. (3认同)

Agi*_*gis 9

Effective Go开始:

如果您循环遍历数组,切片,字符串或映射,或从通道读取,则range子句可以管理循环.

您正在尝试迭代指向切片的指针,该切片是单个值,因此不可能是集合.

将参数更改为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)
    }
}
Run Code Online (Sandbox Code Playgroud)


dom*_*ato 6

如果你需要从*片拉一个单独的元素,你必须取消对它的引用首先是这样的:(*slice)[0].*slice[0]在我意识到这一点之前,我冲了大约6个小时.它与操作顺序有关,而不是IMO,这是一个非常优雅的结果.

我最后写了一些指针接收器方法来进行就地修改,比如追加和弹出更多,在我看来,合理的方式 - 一个例子可以在这里找到:https://play.golang.org/p/qZEYMcPHl4

  • @HassaanSalik-感谢您的支持,因此我将不再这样做。切片已经是指针类型,因此通常不应该需要`* slice`的理由-从那以后我就重构了这段代码,建议您寻找机会做同样的事情。 (2认同)

Mar*_*her 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)
    }
}
Run Code Online (Sandbox Code Playgroud)

我也改变了范围条款,因为我认为你没有修改classes.