range是go提供的一种迭代遍历手段。 range遍历
range遍历可操作的类型有数组(包括字符串)、切片、Map、channel等:
for i := range arraysfor k := range mapsfor range collections
func rangeIndexOnly() {
v := []int{10, 20, 30}
for i := range v {
v[i] *= 2
}
fmt.Println(v)
}
func rangeKeyOnly() {
fruits := map[string]string{"a": "apple", "b": "banana"}
for k := range fruits {
fmt.Printf("%s\n", k)
}
}
func rangeOnly() {
var Counts [5][0]int // no memory occupy
for range Counts { // 五次循环
fmt.Println("Range-Count")
}
}
[0]int
遍历slice
遍历slice前,会先获取其长度作为循环次数;循环体中,每次循环会先获取元素值,若需要index与value的话,则进行赋值;
遍历切片的伪码:
// for_temp := range-slice
// 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
// }
循环开始前循环次数就已经确定了, 所以循环过程中新添加的元素是不会被遍历到的。
ary[index]
遍历数组、切片时,返回(index, value):
nums := []int{2, 3, 4}
sum := 0
for _, num := range nums {
sum += num
}
遍历map
map底层使用hash表实现,插入数据位置是随机的,所以遍历过程中新插入的数据不能保证遍历到(可能会被遍历到,也可能遍历不到)。
遍历map的伪码:
// var hiter map_iteration_struct
// for mapiterinit(type, range, &hiter); hiter.key != nil; mapiternext(&hiter) {
// key_temp = *hiter.key
// value_temp = *hiter.val
// key = key_temp
// value = value_temp
// original body
// }
遍历map时,返回(key,value):
fruits := map[string]string{"a": "apple", "b": "banana"}
for k, v := range fruits {
fmt.Printf("%s -> %s\n", k, v)
}
遍历channel
channel是依次从通道中读取数据:
- 如果通道中没有元素,则会阻塞等待;
- 如果channel已被关闭,则会解除阻塞并退出循环;
遍历通道伪码:
// for {
// value_temp, ok_temp = <-range
// if !ok_temp {
// break
// }
// value = value_temp
// original body
// }
遍历channel时,返回接收到的数据:
ch := make(chan int)
// 发送数据的goroutine
go func() {
for i := 0; i < 5; i++ {
ch <- i+1 //往通道写数据
}
//不需要再写数据时,关闭channel
close(ch)
}()
for num := range ch {
fmt.Println("num = ", num)
}