// Arrange to do a loop appropriate for the type. We will produce // for INIT ; COND ; POST { // ITER_INIT // INDEX = INDEX_TEMP // VALUE = VALUE_TEMP // If there is a value // original statements // }
其中针对 slice 的编译方式如下:
1 2 3 4 5 6 7 8 9
// The loop we generate: // for_temp := range // len_temp := len(for_temp) // for index_temp = 0; index_temp < len_temp; index_temp++ { // value_temp = for_temp[index_temp] // index = index_temp // value = value_temp // original body // }
funcmain() { str := []string{"I","am","bobo"} for _, v := range str{ // 把外部的v值拷贝给函数内部的v gofunc(v string) { fmt.Println(v) }(v) }
time.Sleep(3 * time.Second) }
// output I am bobo
对于slice
由 for range 的原理我们可以知道 for i, v := range x,进入循环前会对x的长度进行快照,决定一共循环len(x)那么多次。后面x的变动不会改变循环次数。通过i,以及最新的x,把x[i]赋予给v。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
package main
import ( "fmt" )
funcmain() { x := []int{1, 3, 5, 7, 9, 11, 13, 15} fmt.Println("start with ", x)
for i, v := range x { fmt.Println("The current value is", v) x = append(x[:i], x[i+1:]...) fmt.Println("And after it is removed, we get", x) } }
上面代码,在遍历切片的时候,每遍历一次就把该元素从切片中删掉
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
//output The current value is 1 And after it is removed, we get [3579111315] The current value is 5 And after it is removed, we get [379111315] The current value is 9 And after it is removed, we get [37111315] The current value is 13 And after it is removed, we get [371115] The current value is 15 panic: runtime error: slice bounds out of range [5:4]
goroutine 1 [running]: main.main() /data1/htdocs/go_project/src/github.com/cnyygj/go_practice/Interview/for_range.go:13 +0x398 exit status 2
从输出我们可以看出,for range 的循环次数取决于循环前会对遍历目标的长度进行快照,并不会随着遍历目标长度的修改而改变。所以最终会出现切片溢出的panic
type Guest struct { id int name string surname string friends []int }
func(self Guest) removeFriend(id int) { for i, other := range self.friends { if other == id { self.friends = append(self.friends[:i], self.friends[i+1:]...) break } } }
func(self *Guest) removeFriend(id int) { for i, other := range self.friends { if other == id { self.friends = append(self.friends[:i], self.friends[i+1:]...) break } } }