go只提供了一种循环方式,即for循环,其中有两种方式。第一种是for [initStmt];[Condition];[PostStmt]{}
for i:=0;i++;i<10{ .... }
第二种是for-range可以用来历容器类型如数组、切片和映射,channel 。但是使用for-range时,如果使用不当会程序运行不是预期结果,例如,下面的示例程序将遍历一个切片,并将切片的值当成切片值存入,切片类型是一个结构体,切片的类型是为Point型,值是一个地址。
package main import "log" /** Created by GoLand GO Version : go1.10.3 Project: Boring Created by Kaifoon Created with 2018/10/8 21:57 **/ type Point struct { x int y int } func main() { r := make([]*Point,4) d := []Point{ {1,3}, {3,3}, {3,48}, {8,2}, } for _,v := range d { r = append(r,&v) } for _,v := range r { log.Println(*v) } }
我们希望结果是
2018/10/08 22:44:50 {1 3} 2018/10/08 22:44:50 {3 3} 2018/10/08 22:44:50 {3 48} 2018/10/08 22:44:50 {8 2} Process finished with exit code 0
但是实际运行是这样的
2018/10/08 22:44:50 {8 2} 2018/10/08 22:44:50 {8 2} 2018/10/08 22:44:50 {8 2} 2018/10/08 22:44:50 {8 2} Process finished with exit code 0
由输出可以知道,程序取最后迭代的值写入。经过debug发现,原来for-range 时 v 是复制切片的的值,然而v的指针地址是没变的。所以迭代完成的时候,因为读取的v的指针,v的地址被写入,装入的值也是最后迭代的值。正确程序如下:
package main import "log" /** Created by GoLand GO Version : go1.10.3 Project: Boring Created by Kaifoon Created with 2018/10/8 21:57 **/ type Point struct { x int y int } func main() { r := make([]*Point,0) d := []Point{ {1,3}, {3,3}, {3,48}, {8,2}, } for _,v := range d { vv := v r = append(r,&vv) } for _,v := range r { log.Println(*v) } }
原文地址:https://www.cnblogs.com/kaifoon/p/9757830.html
时间: 2024-10-14 05:52:38