Golang 语言坑之for-range

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

  

猜你喜欢

转载自www.cnblogs.com/kaifoon/p/9757830.html