I find the accepted answer slightly confusing as it doesn't directly directly address the questions.
So to answer your questions.
for range is one loop style you can use to access the elements in the environment slice returned from os.Environ(), but as I show below you can use the other for loop style. You will see the differences below.
range in this for loop is the construct you use that will provide a copy and the index for each of the elements in the slice.
To summarize, there are basically two forms of the for loop construct in go (actually 3, but we're only concerned with two here).
One uses the range keyword, and the other does not.
The for ... range version creates a copy of the item in the slice you are iterating over. The other, does not and you must access it by reference.
func main() {
for i, env := range os.Environ() {
fmt.Println(i, env)
}
}
Here is how you would write the for loop without using range construct:
func main() {
env := os.Environ()
for i := 0; i < len(env); i++ {
fmt.Println(i, env[i])
}
}
I also found a third option which looks tidy and has the same advantage as option 2.
func main() {
env := os.Environ()
for i := range env {
fmt.Println(i, env[i])
}
}
The first approach is nice and clean, but the second provides better performance because it doesn't do a copy. Both have their place. I would generally use range, but where you need it, the traditional C-like loop is available.
Note: Whenever you are dealing with strings you should always use the range loop as it will return a rune instead of a char. This is particularly important when dealing with internationalisation.
See this blog post about string iteration here: Strings, bytes, runes and characters in Go