Considerations for range in golang in slice and map traversal

  • 2020-06-23 00:40:19
  • OfStack

Considerations for range in slice and map traversal in golang


package main
import (
 "fmt"
)
func main() {
 slice := []int{0, 1, 2, 3}
 myMap := make(map[int]*int)
 for _,v :=range slice{
 if v==1 {
  v=100
 }
 }
 for k,v :=range slice{
 fmt.Println("k:",k,"v:",v)
 }
}

The expected results should be:

[

k: 0 v: 0
k: 1 v: 100
k: 2 v: 2
k: 3 v: 3

]

Pit, but actually

[

k: 0 v: 0
k: 1 v: 1
k: 2 v: 2
k: 3 v: 3

]

The value of slice has not changed. The reason for the above problem is that the traversal of for range is a copy of the original content, so it cannot be used to modify the content in the original slice.

Use k to modify values directly from the index.


for k,v :=range slice{
 if v==1 {
  slice[k]=100
 }
 }

The other one


 package main
  import (
   "fmt"
  )
  func main() {
   s :=[]int{1,2,3,4}
   m :=make(map[int]*int)
   for k,v:=range s{
   m[k]=&v
   }
   for key, value := range m {
   fmt.Printf("map[%v]=%v\n", key, *value)
   }
   fmt.Println(m)
  }

The expected value to be printed should be:

[

map[0]=1
map[1]=2
map[2]=3
map[3]=4

]

Actual results:

[

map[2]=4
map[3]=4
map[0]=4
map[1]=4

]

As we can guess from the above results, range points to the same pointer. With Println we can verify our conjecture

map[1:0xc00008a000 2:0xc00008a000 3:0xc00008a000 0:0xc00008a000] We can see that our guess is correct

Or because actually for range create copies of each element, rather than directly back to each element of reference, if you use the value variable address as a pointer to each element, can lead to errors, in an iterative, return variable is an iterative process, according to a new variable section assignment in turn so value address is always the same, lead to the results than expected.

Declare an intermediate variable, save value, and copy to map


package main
import (
 "fmt"
)
func main() {
 s :=[]int{1,2,3,4}
 m :=make(map[int]*int)
 for k,v:=range s{
 n:=v
 m[k]= &n
 }
 for key, value := range m {
 fmt.Printf("map[%v]=%v\n", key, *value)
 }
 fmt.Println(m)
}

conclusion


Related articles: