06 August 2014

IMG-THUMBNAIL

一般语言都支持两种遍历方式,这里做下介绍。最后介绍一个 For Range 不恰当的使用引起的 Bug。

从大一开始学C++,所接触过的for循环只有一种方式,for (int i = 0; i < count; i++) {...}。后来接触了Java,知道Java 5 引入了一种新特性,可以通过for (a : aa)遍历整个数组。虽然知道,但是也没用过,因为之前那种方法足够了。

现在主力语言是Go。Go也支持传统的写法for i := 0; i < count; i++ {...}。同样,还有一种for i, a := range aa {...}。这个跟Java相比,除了能够遍历,还能得到当前遍历的索引值,所以在Go中,更倾向于后面这种方法,灵活度更高。

今天要对一个数据进行遍历,对每个元素进行稍加修改,才发现,原来这两种方式是有很大区别的。当时使用第二种方式修改之后,一直发现没有修改成功。后来进过调试,才发现是for循环的问题。

测试代码在这里

a := []string{}
a = append(a, "hello")
a = append(a, ", ")
a = append(a, "world")
fmt.Println(a)

for i := 0; i < len(a); i++ {
	fmt.Println(&a[i])
}

for _, aa := range a {
	aa += "@"
	fmt.Println(&aa)
}
for i := 0; i < len(a); i++ {
	a[i] += "@"
	fmt.Println(&a[i])
}
fmt.Println(a)

通过range方式获得的变量,打印出它的地址,和之前的数组a的地址相比,是不同的地址。

[hello ,  world]
0x10322280
0x10322288
0x10322290
0x1030e100
0x1030e100
0x1030e100
0x10322280
0x10322288
0x10322290
[hello@ , @ world@]

这里就可以证明,通过range方式获得的变量,和a[i]变量是不同的,只是里面存的值一样而已。所以,如果做出了修改操作,也不会修改到原来的数组。

果断再去看一下大Java的语法。结果也是一样的。

class TestFor {

	public static void main(String[] args) {
		String[] a = {"hello", ", ", "world"};
		System.out.println(a[0] + a[1] + a[2]);

		for (String aa : a) {
			aa += "@";
		}
		System.out.println(a[0] + a[1] + a[2]);
	}

}

如果遍历数组,还需要对数组元素进行操作,建议用传统for循环因为可以定义角标通过角标操作元素。如果只为遍历获取,可以简化成高级for循环,它的出现为了简化书写。

传统的for,写起来不太方便,但是功能强大;如果只是单纯得遍历,可以使用新的写法,简化代码。


推荐阅读:「通过两个例子介绍一下 Golang For Range 循环原理 」


参考文献

原文链接:Golang——for循环的两种用法,转载请注明来源!

EOF