The for-range is very powerful in Golang, which can be used to iterate over array, slice, channel or map. But there are two semantics of for-range in Golang, which rarely draws attention from developers. In this article, we simply introduce these two semantics of for-range and watch the interesting results.
- value semantic when iterating array
package main
import "fmt"
func main() {
s := [3]string{"a", "b", "c"}
fmt.Println(s[1])
for i, v := range s {
s[1] = "j"
if i == 1 {
fmt.Println(v)
}
}
}
for i, v is way of value semantic, in which it iterates its own copy of the original array s, the whole array is copied, so although s[1] is changed before, the value of v is still b.
Output is as below,
b
b
- pointer semantic when iterating array
package main
import "fmt"
func main() {
s := [3]string{"a", "b", "c"}
fmt.Println(s[1])
for i := range s {
s[1] = "j"
if i == 1 {
fmt.Println(s[1])
}
}
}
for i:= is used as pointer semantic, in which it iterates the original array,
b
j
- value semantic when iterating slice
package main
import "fmt"
func main() {
s := []string{"a", "b", "c"}
fmt.Println(s[1])
for i, v := range s {
s[1] = "j"
if i == 1 {
fmt.Println(v)
}
}
}
and the output,
b
j
for i,v is still value semantic, but the slice includes pointer which points to acutal data, so although it iterates its own copy of slice, the underneath data is the same.
- pointer semantic when iterating slice
package main
import "fmt"
func main() {
s := []string{"a", "b", "c"}
fmt.Println(s[1])
for i := range s {
s[1] = "j"
if i == 1 {
fmt.Println(s[1])
}
}
}
output,
b
j
no big deal, pointer semantic means for-range iterates the original slice.
So when working with array, we must notice the difference between for i, v := and for i :=, meaning value semantic and pointer semantic respectively.