range copy value?

可能一想到 range,就会联想到一些书中提到 range 过程获得的第二变量是原变量的备份,通过修改这个变量的值对原变量是无效的,其实不全对,关键还要看原变量是一个值变量还是一个指针变量。

如下面的代码,a 作为一个值变量,range 过程中想通过修改它的备份 v 的值进而修改 a 中的值,是不对 a 起效的,而 b 作为一个指针变量,它的备份 v(自淫都叫备份)复制的是 b 中的变量的地址,也就是指针的值(指针的值就是地址), 这时通过修改 v 的值是可以修改 b 中变量的值的。

package main

import (
	"fmt"
)

type D struct {
	Arr int
}

func ArrayPinter_PointerArrarDemo() {
	println("<<<-----------------ArrayPinter_PointerArrarDemo----------")
	println("-------copy value------")
	//modification will work during range,copy value?
	a := make([]D, 0, 1)
	a = append(a, D{Arr: 1})
	a = append(a, D{Arr: 134324})

	for k, v := range a {
		fmt.Printf("vxxx%+v: %+v arr:%p\n", k, v, &v.Arr)
		v.Arr = 191
	}

	for k, v := range a {
		fmt.Printf("vooo%+v: %+v arr:%p\n", k, v, &v.Arr)
	}
	// modification will work during range,copy address?
	println("-------copy address------")
	b := make([]*D, 0, 1)
	b = append(b, &D{Arr: 1})
	b = append(b, &D{Arr: 134324})

	for k, v := range b {
		fmt.Printf("pxxx%+v: %+v arr:%p\n", k, v, &v.Arr)
		v.Arr = 191
	}

	for k, v := range b {
		fmt.Printf("pooo%+v: %+v arr:%p\n", k, v, &v.Arr)
	}
	println("-----------------ArrayPinter_PointerArrarDemo------------>>>")
}

func main() {
	ArrayPinter_PointerArrarDemo()
}

运行结果:

<<<-----------------ArrayPinter_PointerArrarDemo----------
-------copy value------
vxxx0: {Arr:1} arr:0x20818c230
vxxx1: {Arr:134324} arr:0x20818c230
vooo0: {Arr:1} arr:0x20818c2a0
vooo1: {Arr:134324} arr:0x20818c2a0
-------copy address------
pxxx0: &{Arr:1} arr:0x20818c2f8
pxxx1: &{Arr:134324} arr:0x20818c300
pooo0: &{Arr:191} arr:0x20818c2f8
pooo1: &{Arr:191} arr:0x20818c300
-----------------ArrayPinter_PointerArrarDemo------------>>>

可见,传值的得到的备份 v, 有自己的地址,range 过程中每次都会把原变量的值 copy 到这个地址对应的值里面,而传指针的得到的备份 v,没有自己的地址,备份的值为地址,v 在这里也是一个指向原变量的指针。

2015-08-13