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