Jump to Navigation

golang容器循环时的修改

golang容器循环时的修改

golang中的原生容器有,slice/map/array

它们都支持range循环遍历,而在遍历时,有可能有修改当前容器的需要。

虽然一般不建议这么使用,但是golang也没有禁止这么使用,还是了解一点它的真实情况好些。

map测试

添加key时的测试

 var m1 = make(map[int]int, 0)
 for n := 0; n < 5; n++ {
      m1[n] = 100 + n
 }

 idx := 0
 for key, val := range m1 {
      log.Println(idx, key, val)
      m1[key+10] = m1[key] + 1000
      idx += 1
 }

 log.Println("============")
 idx = 0
 for key, val := range m1 {
      log.Println(idx, key, val)
      idx += 1
 }

得到的结果为:

2016/03/29 12:03:18 0 3 103
2016/03/29 12:03:18 1 4 104
2016/03/29 12:03:18 2 13 1103
2016/03/29 12:03:18 3 14 1104
2016/03/29 12:03:18 4 23 2103
2016/03/29 12:03:18 5 0 100
2016/03/29 12:03:18 6 1 101
2016/03/29 12:03:18 7 2 102
2016/03/29 12:03:18 ============
2016/03/29 12:03:18 0 0 100
2016/03/29 12:03:18 1 14 1104
2016/03/29 12:03:18 2 13 1103
2016/03/29 12:03:18 3 23 2103
2016/03/29 12:03:18 4 24 2104
2016/03/29 12:03:18 5 33 3103
2016/03/29 12:03:18 6 1 101
2016/03/29 12:03:18 7 2 102
2016/03/29 12:03:18 8 3 103
2016/03/29 12:03:18 9 4 104
2016/03/29 12:03:18 10 10 1100
2016/03/29 12:03:18 11 11 1101
2016/03/29 12:03:18 12 12 1102

添加key时,会得到奇异的结果,无法确保在本次循环中全部遍历或者不遍历新key。

但是,跳出本次循环之后,再次循环时,可以发现也并不是预期所有的新key全是[10-20]的,

因为有些key在第一次循环内就被二次取到,再以其为基础生成了新key,出现了key>20的情况。

看第二次只读取的 range 循环,得到的结果其实就已经完全不对了。

修改key时的测试:

 var m1 = make(map[int]int, 0)
 for n := 0; n < 5; n++ {
      m1[n] = 100 + n
 }

 idx := 0
 for key, val := range m1 {
      log.Println(idx, key, val)
      m1[idx+1] = m1[idx+1] + 10000
      idx += 1
 }

 log.Println("============")
 idx = 0
 for key, val := range m1 {
      log.Println(idx, key, val)
      idx += 1
 }

结果:

2016/03/29 12:10:32 0 3 103
2016/03/29 12:10:32 1 4 104
2016/03/29 12:10:32 2 0 100
2016/03/29 12:10:32 3 1 10101
2016/03/29 12:10:32 4 2 10102
2016/03/29 12:10:32 ============
2016/03/29 12:10:32 0 0 100
2016/03/29 12:10:32 1 1 10101
2016/03/29 12:10:32 2 2 10102
2016/03/29 12:10:32 3 3 10103
2016/03/29 12:10:32 4 4 10104
2016/03/29 12:10:32 5 5 10000

修改key时,同样在一次循环内,无法确保在本次循环中全部遍历或者不遍历新key。

但是,跳出本次循环之后,再次循环时,其实map的值也很难道预期是否是想要的结果。

删除key时的测试:

 var m1 = make(map[int]int, 0)
 for n := 0; n < 5; n++ {
      m1[n] = 100 + n
 }

 idx := 0
 for key, val := range m1 {
      log.Println(idx, key, val)
      delete(m1, idx+1)
      idx += 1
 }

 log.Println("============")
 idx = 0
 for key, val := range m1 {
      log.Println(idx, key, val)
      idx += 1
 }

结果:

2016/03/29 12:13:14 0 4 104
2016/03/29 12:13:14 1 0 100
2016/03/29 12:13:14 2 3 103
2016/03/29 12:13:14 ============
2016/03/29 12:13:14 0 0 100
2016/03/29 12:13:14 1 4 104

删除key时,range遍历却是对的,一旦被delete掉,range不会再出现。

结果,容易产生细节迷惑,修改的完全不可靠,很可能和预期的结果不一样,

还是在遍历时用新map存储修改结果更可靠。

添加新评论

Plain text

  • 不允许HTML标记。
  • 自动将网址与电子邮件地址转变为链接。
  • 自动断行和分段。
CAPTCHA
This question is for testing whether or not you are a human visitor and to prevent automated spam submissions.
Image CAPTCHA
Enter the characters shown in the image.


Main menu 2

Story | by Dr. Radut