您的位置 首页 golang

chain33区块链开发教程:Golang 的 for 语句迭代变量和闭包

1、如何在for range 中使用 闭包

我们先看一个示例:

1. package main

2.

3. import (

4. “fmt”

5. “time”

6. )

7.

8. type field struct {

9. name string

10. }

11.

12. func (p *field) print() {

13. fmt.Println(p.name)

14. }

15.

16. func main() {

17. data := []field{{“a”},{“b”},{“c”}}

18.

19. for _,v := range data {

20. go v.print()

21. }

22.

23. time.Sleep(3 * time.Second)

24. }

该示例输出结果为:

2、问题思考

为什么输出的结果不是 a, b, c 呢?

在 go v.print() 前面添加 fmt.Printf(“&v=%p v=%s\n”, &v, v),打印一下 v的地址, 输出结果为:

打印出 v 的地址都是相同的。

for _,v := range data { // for语句中的迭代变量(如: v)在每次迭代时被重新使用, 一直复用。

go v.print() // 此处可理解为: go (&v).print(), 也就是用 v 的指针去调用,而且 v 会在每次迭代时复用, 所以每一个调用的 receiver 都是共同指向 v 的指针, 而且v在最后一次迭代后, 被赋值为:”c”, 所以才有了打印出3个”c”的结果。

3、解决方案

方法一: data 声明为指针类型

代码如下:

1. package main

2.

3. import (

4. “fmt”

5. “time”

6. )

7.

8. type field struct {

9. name string

10. }

11.

12. func (p *field) print() {

13. fmt.Println(p.name)

14. }

15.

16. func main() {

17. data := []*field{{“a”}, {“b”}, {“c”}}

18.

19. for _, v := range data {

20. go v.print() //v本身就是指针,指向a,b,c; 迭代时会改变指向,直接调用没有复制,故每次调用时v都是分别指向a,b,c的地址值

21. }

22.

23. time.Sleep(3 * time.Second)

24. }

方法二: for 循环中保存当前迭代变量的值

代码如下:

1. package main

2.

3. import (

4. “fmt”

5. “time”

6. )

7.

8. type field struct {

9. name string

10. }

11.

12. func (p *field) print() {

13. fmt.Println(p.name)

14. }

15.

16. func main() {

17. data := []field{{“a”}, {“b”}, {“c”}}

18.

19. for _, v := range data {

20. temp := v //保存当前迭代变量

21. go temp.print()

22. }

23.

24. time.Sleep(3 * time.Second)

25. }

4、总结

当方法定义时为Pointer receiver

如: func (p *field) print() 时

(1) Pointer Receive不复制,所以当以值方式调用时,直接 &value取地址作为pointer receiver;

(2)若for _,v := range, data中的v本身就是指针, 则直接调用;

(3)for range会在每次迭代中一直复用迭代变量(如: v)。

文章来源:智云一二三科技

文章标题:chain33区块链开发教程:Golang 的 for 语句迭代变量和闭包

文章地址:https://www.zhihuclub.com/98892.shtml

关于作者: 智云科技

热门文章

网站地图