range 是 Go 語言中一個用於迭代數組、切片、通道等集合類型的關鍵字,使用 range 關鍵字語法可以使程式碼更簡潔清晰。在使用 range 進行迭代時,需要注意一些細節和不同場景的差異。
迭代數組和切片時,range 傳回兩個值:索引和元素值。使用 _ 佔位符可以省略其中的一個值。
範例:
arr := [5]int{1, 2, 3, 4, 5} for index, value := range arr { fmt.Printf("index: %d, value: %d\n", index, value) } sli := []string{"hello", "world", "golang"} for i, v := range sli { fmt.Printf("i: %d, v: %s\n", i, v) }
在迭代數組或切片時,如果只需要索引或元素值,可以將對應的變數以 _ 佔位符來忽略。例如:
arr := [5]int{1, 2, 3, 4, 5} for index, _ := range arr { fmt.Printf("index: %d\n", index) } sli := []string{"hello", "world", "golang"} for i := range sli { fmt.Printf("i: %d\n", i) }
迭代 map 時,range 傳回兩個值:鍵和值。與數組區別的是,這裡傳回的是鍵值對而非索引和元素值。
範例:
m := map[string]int{"a":1, "b":2, "c":3} for key, value := range m { fmt.Printf("key: %s, value: %d\n", key, value) }
迭代map 時同樣可以使用_ 忽略其中一個值:
m := map[string]int{"a":1, "b":2, "c":3} for k := range m { fmt.Println("key:", k) }
迭代字串時,range 傳回兩個值,第一個值為字元的索引,第二個值是這個索引處的字元值。需要注意的是,在程式編譯期間,字串會被轉換為一個位元組數組,因此迭代的是位元組而非字元。
範例:
str := "hello,世界!" for index, ch := range str { fmt.Printf("index: %d, char: %c\n", index, ch) }
#在迭代通道時,range 會不停地阻塞,等待通道中有內容可讀取。當通道關閉或讀取完成時,range 循環終止。 range 循環中的變數為接受通道值的變數。
範例:
ch := make(chan int, 10) go func() { for i := 0; i < 10; i++ { ch <- i } close(ch) }() for val := range ch { fmt.Println("value:", val) }
在使用通道時,特別需要注意的是,如果通道中的值不會被讀取,會導致程式卡死。可以使用帶有緩衝的通道或使用 select 語句來解決該問題。
緩衝通道範例:
ch := make(chan int, 10) go func() { for i := 0; i < 10; i++ { ch <- i } close(ch) }() for { select { case val, ok := <-ch: if !ok { return } fmt.Println("value:", val) default: // 通道中没有值可读 } }
在使用range 進行循環迭代時,必須注意循環變數重複使用的問題。在循環內部使用變數時,需要將其複製給新的變量,否則會出現資料覆蓋的問題。
範例:
// 错误示例 sli := []int{1, 2, 3} for _, v := range sli { go func() { fmt.Println(v) // 输出结果都是 3 }() } // 正确示例 sli := []int{1, 2, 3} for _, v := range sli { val := v // 复制变量 go func() { fmt.Println(val) }() }
總之,range 是 Go 語言中非常實用的一個關鍵字,可以幫助我們迭代集合中的元素。在使用 range 時需要注意迭代不同類型的集合時傳回值的區別,以及循環變數重複使用的問題。
以上是golang怎麼使用range進行迭代的詳細內容。更多資訊請關注PHP中文網其他相關文章!