Go语言 range 循环语句

    /    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)

分享至