golang之range遍历

文章目录


range是go提供的一种迭代遍历手段。

range遍历

range遍历可操作的类型有数组(包括字符串)、切片、Map、channel等:

  • index、value接收range返回值会发生一次数据拷贝;根据情况放弃接收index或value(使用_),可一定程度上提升性能;
  • 对于channel,没有数据时,会被阻塞;
  • 尽量避免遍历过程中修改原数据;

遍历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
// }

循环开始前循环次数就已经确定了, 所以循环过程中新添加的元素是不会被遍历到的。

遍历数组、切片时,对value的修改不会影响数组、切片中的原有数据;要修改原来的数据,需要使用下标(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)
    }
上一篇:create database ,drop database ,show Databases,use 数据库 ,怎么使用?


下一篇:react结合ant design的管理系统