9

I have a fairly simple question, but can't find answer anywhere. I'm iterating over a range of slices, like this:

for index, arg := range os.Args[1:] {
    s += fmt.Sprintf("%d: %s", index, arg)
}

As I understand range iterates over a slice, and index is created from range, and it's zero-based. I get the output:

0: argument_1
1: argument_2
// etc.

But it's not what I expect - I need range to preserve indices of that slice, so my output looks like this:

1: argument_1
2: argument_2
// etc.

The most obvious way to achieve this is to add shift on index in loop:

shift := 1
for index, arg := range os.Args[shift:] {
    index += shift
    s += fmt.Sprintf("%d: %s", index, arg)
}

But I was wondering, is there more "Go-ish" way to do this, and also, how to preserve indices when creating a slice in Go like this?

Damaged Organic
  • 8,175
  • 6
  • 58
  • 84
  • In your `shift` example you are adding 1 to the index each time in addition to the usual increment of the for loop. Wouldn't this resolve in reading only arguments 1, 3, 5, etc ? – Matei Radu Jan 03 '17 at 14:22
  • 2
    @MateiRadu No, index is reassigned for every loop so the code works. It would probably look better with a new variable like `originalIndex := index + 1` though – Franck Jeannin Jan 03 '17 at 14:29
  • @FranckJeannin Thanks for the explanation, it cleared my doubts on how `range` works. – Matei Radu Jan 03 '17 at 14:42

1 Answers1

7

There is nothing wrong with your original code, when you are doing os.Args[1:] you are creating a new slice which like any slice starts at index 0.
It's a matter of style (and performance) but you could also do this:

for index, arg := range os.Args {
    if index < 1 {
        continue
    }
    s += fmt.Sprintf("%d: %s", index, arg)
}
Franck Jeannin
  • 6,107
  • 3
  • 21
  • 33