1. for-range改变内容问题

  1. type User struct {
  2. Name string
  3. Age int
  4. }
  5. func main() {
  6. u := []User{
  7. {"a", 1},
  8. {"b", 2},
  9. {"c", 3},
  10. }
  11. for i, v := range u {
  12. //v.Age = 1231 // v是值拷贝 无法修改,但v是一个变量,只会被定义一次
  13. u[i].Age = 1231 // 利用下标修改
  14. }
  15. fmt.Println(u)
  16. }
  17. //[{a 1231} {b 1231} {c 1231}]

2. 是否发生死循环

  1. func main() {
  2. //不会造成死循环, range会对切片做拷贝,新增的数据并不在拷贝内容中,并不会发生死循环。
  3. //这种题一般会在面试中问,留意下。
  4. nums := []int{1, 2, 3}
  5. for i, _ := range nums {
  6. nums = append(nums, i+100)
  7. }
  8. fmt.Println(nums)
  9. }
  10. //[1 2 3 100 101 102]

3. 指针数据问题

  1. type User struct {
  2. Name string
  3. Age int
  4. }
  5. func main() {
  6. u := []User{
  7. {"a", 1},
  8. {"b", 2},
  9. {"c", 3},
  10. }
  11. n := []*User{}
  12. for _, v := range u {
  13. //v被拷贝过不同的值,但加入的是同一个v的地址
  14. n = append(n, &v)
  15. }
  16. fmt.Println(n) // 打印三个相同的地址
  17. }
  18. // [0xc00000c060 0xc00000c060 0xc00000c060]
  19. // 1.加入一个中间变量解决
  20. for _, v := range u {
  21. //v被拷贝过不同的值,但加入的是同一个v的地址
  22. a := v
  23. n = append(n, &a)
  24. }
  25. // 2.取原数组地址
  26. for i, _ := range u {
  27. n = append(n, &u[i])
  28. }

4. map 使用 for-range

The iteration order over maps is not specified and is not guaranteed to be the same from one iteration to the next. If map entries that have not yet been reached are removed during iteration, the corresponding iteration values will not be produced. If map entries are created during iteration, that entry may be produced during the iteration or may be skipped. The choice may vary for each entry created and from one iteration to the next. If the map is nil, the number of iterations is 0. 翻译: 未指定map的迭代顺序,并且不能保证每次迭代之间都相同。 如果在迭代过程中删除了尚未到达的映射条目,则不会生成相应的迭代值。 如果映射条目是在迭代过程中创建的,则该条目可能在迭代过程中产生或可能被跳过。 对于创建的每个条目以及从一个迭代到下一个迭代,选择可能有所不同。 如果映射为nil,则迭代次数为0。

  1. //可以成功删掉
  2. func main() {
  3. mp := map[int]int{
  4. 1: 1,
  5. 2: 2,
  6. 3: 3,
  7. }
  8. for k := range mp {
  9. if k == 1 {
  10. delete(mp, k)
  11. }
  12. }
  13. fmt.Println(mp)
  14. }
  15. //map[2:2 3:3]
  1. //添加
  2. func main() {
  3. var addMap = func() {
  4. mp := map[int]int{
  5. 1: 1,
  6. 2: 2,
  7. 3: 3,
  8. }
  9. for k, v := range mp {
  10. mp[100] = 12
  11. fmt.Print(k, ":", v, " ")
  12. }
  13. }
  14. for i := 0; i < 10; i++ {
  15. addMap()
  16. fmt.Println()
  17. }
  18. }
  19. /*
  20. 1:1 2:2 3:3
  21. 1:1 2:2 3:3 100:12
  22. 1:1 2:2 3:3 100:12
  23. 3:3 100:12 1:1 2:2
  24. 1:1 2:2 3:3
  25. 2:2 3:3 100:12 1:1
  26. 1:1 2:2 3:3 100:12
  27. 1:1 2:2 3:3
  28. 2:2 3:3 100:12 1:1
  29. 1:1 2:2 3:3 100:12
  30. */

从运行结果,我们可以看出来,每一次的结果并不是确定的。这是为什么呢?这就来揭秘,map内部实现是一个链式hash表,为了保证无顺序,初始化时会随机一个遍历开始的位置。

所以新增的元素是否被遍历到就变的不确定了

同样删除也是一个道理,但是删除元素后边就不会出现,所以一定不会被遍历到