Fork me on GitHub

Go语言开发-集合类型-遍历切片

4.2.2. 遍历切片

一种常见的需求是遍历切片中的所有元素。如果我们想要得到切片中的元素但却不希望修改该元素,我们可以使用for … range循环;如果我们需要修改切片中的元素,我们可以使用带有循环计数器的for循环。对于前者,下面是一个例子。

for … range循环会初始化一个从0开始的循环计数器,在本例中我们使用了空白标识符(-)丢弃该值,同时从切片中拷贝相应元素的副本。拷贝操作是廉价的(因为它们通过引用传递)。这意味着对元素的任何修改只会影响该副本,而不会影响切片中的元素。

当然,我们可以使用切分操作来遍历切片的一部分。例如,如果我们只想遍历切片的前五个元素,我们可以使用for _,amount:=rangeamounts[:5]语句。

如果我们想要修改切片中的元素,就必须要使用for循环,它作用的是切片的有效索引而不是切片元素的副本。

这里我们将切片中的每个元素增加5%并计算其累加之和。

当然,切片也可以包含自定义类型的元素。下面是一个只有一个自定义方法的自定义类型。

上面的代码定义了一个具有一个字符串和一个float64类型字段的结构体Product,同时我们也定义了一个String()方法来使用%v格式符来打印Product中的元素。(之前我们介绍过打印格式符,也简单介绍了自定义类型和方法,在第6章我们将会详细介绍它们。)

这里我们创建了一个指向Products ([]*Product)的指针切片,并使用三个*Products将其初始化。而之所以可以这样做是因为Go语言足够智能可以意识到[]*Product需要的是指向Products的指针。这里我们使用的是简写形式,products := []*Product{&Product{“Spanner”, 3.99}, &Product{“Wrench”, 2.49}, &Product{“Screwdriver”, 1.99}}。(在4.1节,我们使用了&Type{}语法来创建一个该类型的新值并获取指向它的指针。)

如果我们没有定义Product.String()方法,则%v(在fmt.Println()和一些类似的函数中是被隐式使用的)打印的是Products的内存地址而不是Products本身。此外需要注意的是,Product.String() 方法接受的是Product类型的值而不是* Product,不过这并不成问题,因为Go语言足够智能,它能够自动将*Products解引用,以使我们自定义的方法可以正常工作。

之前我们提到过for … range循环不能用来修改它所遍历的元素,但是这里我们成功的将切片products中的prices都增大了。在每一次遍历中,product变量都被赋值为*Product的副本;它是一个指向切片products中的元素的指针。因此,我们所做的修改是作用于指向的Product值而不是*Product指针的副本。


目录


作者:Johnson
原创文章,版权所有,转载请保留原文链接。

发表评论

电子邮件地址不会被公开。 必填项已用*标注