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) } }