/ 2018-11-28
Go 语言中 range 关键字用于 for 循环中迭代数组(array)、切片(slice)、通道(channel)或集合(map)的元素。在数组和切片中它返回元素的索引和索引对应的值,在集合中返回 key-value 对的 key 值。
字符串遍历
1)for range 英文字符串,key 值按照+1顺序递增
package main import ( "fmt" ) func main() { var str string = "oldboy" for k, v := range str { fmt.Println(k, string(v)) } }
2)for range 包含中文的字符串,英文字符 key 值按照+1顺序递增,中文字符 key 值按照+3顺序递增
package main import ( "fmt" ) func main() { var str string = "老男孩IT教育,只培养技术精英。" for k, v := range str { fmt.Println(k, string(v)) } }
数组遍历
1)for range 数组程序会复制对象,key、value 都是从复制品中取出
package main import ( "fmt" ) func main() { arr := [5]int{1, 2, 3, 4, 5} for k, v := range arr { if k == 0 { arr[0], arr[1] = 1000, 1000 fmt.Println("修改原数组:", arr) } // 使用复制品中取出的 value 修改原数组 arr[k] = v + 100 } fmt.Println(arr) }
2)多维数组遍历
package main import ( "fmt" ) func main() { var arr [2][3]int = [2][3]int{{1, 2, 3}, {2, 4, 6}} for k1, v1 := range arr { for k2, v2 := range v1 { fmt.Printf("%d*%d=%d ", k1+1, k2+1, v2) } fmt.Printf("\n") } }
3)数组遍历值拷贝行为会造成性能问题,建议数组遍历使用引用类型slice,或数组指针
package main import "fmt" func main() { arr := [5]int{1, 2, 3, 4, 5} arrP := &arr for k, _ := range arrP { if k == 0 { arrP[0], arrP[1] = 1000, 1000 fmt.Println("修改原数组:", arr) } arrP[k] += 100 } fmt.Println(arr) }
slice 遍历
将所需数据 copy 到较小的 slice,以便释放底层数组内存
package main import ( "fmt" ) func main() { arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9} slice := arr[:] for key, value := range slice { fmt.Printf("key: %v , value : %v\n", key, value) } }
map 遍历
map 遍历不能保证迭代返回次序,通常是随机结果,具体和版本实现有关
package main import ( "fmt" ) func main() { m := map[int]string{ 1: "oldboy", 2: "Linux", 3: "Golang", 4: "Python", 5: "Java", 6: "DBA", } for k, v := range m { fmt.Printf("%d => %s \n", k, v) } }
channel 遍历
package main import "fmt" func main() { var ch chan int ch = make(chan int, 10) for i := 0; i < 10; i++ { ch <- i } close(ch) for v := range ch { fmt.Println(v) } }
注意:如果没有 close() 因为存入管道10个数字,然后无限取数据,在取出来第10个数据,在次range管道,会dead lock。
(4)