Original post

Hello all,

I’m pretty new to , just started learning it 6 weeks ago. I’m coming from using Python for the last 3 years, and am 100% self-taught (my ADHD makes it exceptionally hard to take formal classes or read a book cover to cover.

Anyways, I am building my first Go project for work and have come across what may be a fairly trivial issue, but I haven’t been able to find a post on this specific question.

When ranging over a slice of structs, is it more efficient to range over the element or the index?

To start, here are my project requirements and the approach I’m taking:
I work for a nationwide retailer and am building a script that puts stores in like groups, based on the last full quarter of sales data. Comparing total sale volume, top items sold, source warehouse and relative location.

To do this, I have built a series of structs and typed slices of those structs. (I’ve redacted some of the code due to company IP rules)

Below is some of my code along with two functions that demonstrate the two approaches.

In addition to thoughts on which approach is more memory efficient, any general feedback on my code would also be greatly appreciated! I’m too far in to this project to make significant changes, but I will definitely take note for application in future projects.

type storeMaster struct {
        store      int
        location   storeLocation
        department storeDepartment
}

type storeLocation struct {
        warehouse int
        postal int
}

type storeDepartment struct {
        department int        //department id (for grouping stores at a department level)
        weeks      int        //count of weeks with active sales
        retail     float64    // $$
        avgRetail  float64    // $$ retail / float64(weeks)
        lastWeek   int        //most recent week with sales
        items      storeItemSlice 
}

type storeItem struct {
        upc       int64
        weeks     int        //count of weeks with active sales for item
        retail    float64    // $$
        avgRetail float64    // $$ retail / float64(weeks)
        lastWeek  int        //most recent week with sales for item
}

type storeMasterSlice []storeMaster
type storeItemSlice []storeItem

func (u storeItemSlice) Len() int           { return len(u) }
func (u storeItemSlice) Less(i, j int) bool { return u[i].avgRetail > u[j].avgRetail }
func (u storeItemSlice) Swap(i, j int)      { u[i], u[j] = u[j], u[i] }
func (u storeItemSlice) Sort()              { sort.Sort(u) }

// function that ranges over the elements
func (m *storeMaster) topItems() (top10, top25, top50 []int64) {
        var items storeItemSlice

        weeks, lastWeek := (*m).maxWeek()

        weeks = math.Round(float64(weeks) * .75)
        lastWeek = lastWeek - 3

        for _, item := range (*m).department.items {
                if item.weeks >= weeks && item.lastWeek >= lastWeek {
                        items = append(items, item)
                }
        }

        items.Sort()

        for i := 0; i < 50; i++ {
                top50 = append(top50, items[i].upc)
        }
        top25 = top50[:25]
        top10 = top50[:10]

        return top10, top25, top50
}

// function that ranges over the index
func (m *storeMaster) maxWeek() (weeks, lastWeek int) {
        for i := range (*m).department.items {
                if (*m).department.items[i].weeks > weeks {
                        weeks = *m.department.items[i].weeks
                }
                if (*m).department.items[i].lastWeek > lastWeek {
                        lastWeek = (*m).department.items[i].lastWeek
                }
        }

        return weeks, lastWeek
}

Thank you in advance for any feedback you can give me! :slight_smile: