golang range 与 iteration 之间的关系

原文地址:https://medium.com/golangspec/range-clause-and-the-address-of-iteration-variable-b1796885d2b7

  1. package main

  2. import (

  3. "fmt"

  4. )

  5. type T struct {

  6. id int

  7. }

  8. func main() {

  9. t1 := T{id: 1}

  10. t2 := T{id: 2}

  11. ts1 := []T{t1, t2}

  12. ts2 := []*T{}

  13. for _, t := range ts1 {

  14. ts2 = append(ts2, &t)

  15. }

  16. for _, t := range ts2 {

  17. fmt.Println((*t).id)

  18. }

  19. }

先不要看结果, 自己想想输出是什么?

对于很多人(包括我自己), 结果可能会让人感到惊讶

  1. 2

  2. 2

我个人期待的结果, 但是这是一个错误结果

  1. 1

  2. 2

迭代变量 t使用短变量声明的方式声明, 它的声明周期就是 for代码块. 这个变量在第一次循环时是第一个元素的值, 在第二次循环时是第二个元素的值, 但是在内存的某个地方保存着slice被遍历结束时的值. t没有指向slice底层数组指向的值–这是一个临时的桶, 下一个元素会覆盖当前值. t是一个辅助变量来保存当前迭代的元素, 所以 &t每次循环都是相同的值

  1. t1 := T{id: 1}

  2. t2 := T{id: 2}

  3. ts1 := []T{t1, t2}

  4. ts2 := []*T{}

  5. for _, t := range ts1 {

  6. t.id = 3

  7. ts2 = append(ts2, &t)

  8. }

  9. for _, t := range ts2 {

  10. fmt.Println((*t).id)

  11. }

  12. fmt.Println(ts1)

  13. fmt.Println(t1)

  14. fmt.Println(t2)

output:

  1. 3

  2. 3

  3. [{1} {2}]

  4. {1}

  5. {2}

可能的解决方案是使用 index去获得slice元素的地址

  1. t1 := T{id: 1}

  2. t2 := T{id: 2}

  3. ts1 := []T{t1, t2}

  4. ts2 := []*T{}

  5. for i, _ := range ts1 {

  6. ts2 = append(ts2, &ts1[i])

  7. }

  8. for _, t := range ts2 {

  9. fmt.Println((*t).id)

  10. }

output:

  1. 1

  2. 2

参考资料

https://golang.org/ref/spec#For_range

推荐阅读


喜欢本文的朋友,欢迎关注“Go语言中文网

golang range 与 iteration 之间的关系

Go语言中文网启用信学习交流群,欢迎加微信274768166,投稿亦欢迎

本文来源于互联网:golang range 与 iteration 之间的关系

Click to rate this post!
[Total: 0 Average: 0]

人已赞赏
Go语言技术开发

Golang Gin 实战(十)| XML渲染

2020-4-18 1:54:32

Go语言技术开发

为什么我会选择golang做Goby的开发语言

2020-4-18 1:54:47

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
有新消息 消息中心
搜索