[Go] Range 探討

程式語言:Go
官網定義

簡介:Range 探討

range 會在執行 for 之前,被完整的執行過一次
也就是拆開的結果會被存在另一個變數中,再依序此變數執行 for 內的動作
但此變數是值還是位址,取決於不同的類型
而這只是通則,不適用在 map 上
Range expression                          1st value          2nd value

array or slice  a  [n]E, *[n]E, or []E    index    i  int    a[i]       E
string          s  string type            index    i  int    see below  rune
map             m  map[K]V                key      k  K      m[k]       V
channel         c  chan E, <-chan E       element  e  E

程式碼

array
取決是值 or 位址,決定是否會更改值
The Go Playground
package main

import (
    "fmt"
)

func main() {
    arr := [5]int{1, 2, 3, 4, 5}
    for i, v := range arr {
        arr[4] = 100 // 不改值
        fmt.Printf("index:%d value:%d type:%T\n", i, v, v)
    }
    fmt.Println()
    for i, v := range &arr {
        arr[4] = 100 // 改值
        fmt.Printf("index:%d value:%d type:%T\n", i, v, v)
    }
}
slice
新增不影響,即使容量事先宣告
但修改值,若曾先 append 過,當原本的 cap 值不夠時,會被重新分配新的底層 array
The Go Playground
package main

import (
 "fmt"
)

func main() {
    arr1 := []int{1, 2, 3, 4, 5}
    for i, v := range arr1 {
        arr1[4] = 100
        fmt.Printf("index:%d value:%d type:%T\n", i, v, v)
    }
    fmt.Println()
    arr2 := []int{1, 2, 3, 4, 5}
    for i, v := range arr2 {
        arr2 = append(arr2, 6)
        arr2[4] = 100
        fmt.Printf("index:%d value:%d type:%T\n", i, v, v)
    }
    fmt.Println()
    arr3 := make([]int, 5, 10)
    arr3[0] = 1
    arr3[1] = 2
    arr3[2] = 3
    arr3[3] = 4
    arr3[4] = 5
    for i, v := range arr3 {
        arr3 = append(arr3, 6)
        arr3[4] = 100
        fmt.Printf("index:%d value:%d type:%T\n", i, v, v)
    }
}
string
不更改值,新增也不影響
The Go Playground
package main

import (
    "fmt"
)

func main() {
    str := "12345"
    for i, c := range str {
        str = "92345678"
        fmt.Printf("i:%d v:%c type:%T\n", i, c, c)
    }
}
map
可能改值,可能不更改值,取決是否已跑過
可能加入,可能不加入,取決於 buffer,但仍是隨機
The Go Playground
package main

import (
    "fmt"
)

func main() {
    m1:= make(map[string]string)

    m1["1"] = "1"
    m1["2"] = "2"
    m1["3"] = "3"
    m1["4"] = "4"
    m1["5"] = "5"
    m1["6"] = "6"
    for k, v := range m1{
        m1["1"] = "100"
        m1["6"] = "100"
        m1["7"] = "7"
        m1["8"] = "8"
        m1["9"] = "9"
        m1["10"] = "10"
        m1["11"] = "11"
        m1["12"] = "12"
        fmt.Printf("k:%s v:%s type:%T\n", k, v, v)
    }
    fmt.Println()
    m2:= make(map[string]string,500)

    m2["1"] = "1"
    m2["2"] = "2"
    m2["3"] = "3"
    m2["4"] = "4"
    m2["5"] = "5"
    m2["6"] = "6"
    for k, v := range m2{
        m2["7"] = "7"
        m2["8"] = "8"
        m2["9"] = "9"
        m2["10"] = "10"
        m2["11"] = "11"
        m2["12"] = "12"
        fmt.Printf("k:%s v:%s type:%T\n", k, v, v)
    }
}
channel
取決傳入值的性質,決定是否更改值與加入
The Go Playground
package main

import (
    "fmt"
)

func run(c chan int){
    arr := [5]int{1, 2, 3, 4, 5}
    for _, v := range arr {
        c <- v
    }
    close(c)
}

func main() {
    c := make(chan int)
    go run(c)
    for v := range c{
        fmt.Printf("value:%d type:%T\n", v, v)
    }
}
The Go Playground
package main

import (
    "fmt"
)

func run(c chan [5]int){
    arr := [5]int{1, 2, 3, 4, 5}
    c <- arr
    close(c)
}

func main() {
    c := make(chan [5]int)
    go run(c)
    for v := range c{
        fmt.Printf("value:%d type:%T\n", v, v)
    }
}

參考

聊聊Golang中的range关键字

留言