編程學習網 > 編程語言 > go > Go 語言 range 解析
2020
05-30

Go 語言 range 解析



range

range 關鍵字在 go 語言中是相當常用好用的語法糖,可以用在 for 循環中迭代 array、slice、map、channel、字符串所有涉及到遍歷輸出的東西。

基本原理

怎么用?

我們在前一節循環中初次觸及到了 range,也知道他可以省略key,或者省略value來循環遍歷的特性,但是這種特性要結合實際情況考量該用哪一個。

切片迭代

 nums := []int{123}
 for k, v := range nums {
  fmt.Printf("key: %v , value: %v  \n", k, v)
 }

這和迭代方式非常適合用for-range語句,如果減少賦值,直接索引num[key]可以減少損耗。如下

for k, _:= range nums {

map迭代注意,從 Go1開始,遍歷的起始節點就是隨機了。

 kvs := map[string]string{
  "a":"a",
  "b":"b",
 }
 for k, v := range kvs {
  fmt.Printf("key: %v , value: %v  \n", k, v)
 }

函數中for-range語句中只獲取 key 值,然后跟據 key 值獲取 value 值,雖然看似減少了一次賦值,但通過 key 值查找 value 值的性能消耗可能高于賦值消耗。

所以能否優化取決于 map 所存儲數據結構特征、結合實際情況進行。

字符串迭代(一個一個的輸出字符)

for k,v := range "hello"{
  //注意這里單個字符輸出的是ASCII碼,   //用 %c 代表輸出字符   fmt.Printf("key: %v , value: %c
    \n", k, v)
 }

channel (如果不會可以先 mark 下,詳細參考后續:go 的并發特性章節)

ch := make(chan int10)
 ch <- 11  ch <- 12  close(ch) // 不用的時候記得關掉,不關掉又沒有另一個goroutine存在會死鎖哦,可以注釋掉這一句體驗死鎖  for x := range ch {
  fmt.Println(x)
 }

結構體

tmp := []struct{
  int   string  }{
  {1"a"},
  {2"b"},
 }

 for k,v := range tmp{
  fmt.Printf("k:%v, v:%v  \n",k,v)
 }

注意:由于循環開始前循環次數就已經確定了,所以循環過程中新添加的元素是沒辦法遍歷到的。

有可能會遇到的坑!

由于range遍歷時value是值的拷貝,如果這個時候遍歷上一節聲明的結構體時,修改value,原結構體不會發生任何變化!

for _,v := range tmp{
  v.a = 2  }

兩次輸出一致

k:0, v:{1 a}  
k:1, v:{2 b}  
k:0, v:{1 a}  
k:1, v:{2 b}  

編程 Tips

  • 遍歷過程中可以適情況放棄接收 index  value,可以一定程度上提升性能
  • 遍歷 channel 時,如果 channel 中沒有數據,可能會阻塞
  • 盡量避免遍歷過程中修改原數據

總結

  • range可以用于for 循環中迭代 array、slice、map、channel、字符串所有涉及到遍歷輸出的東西。
  • for-range 的實現實際上是C風格的for循環
  • 使用index,value接收range返回值會發生一次數據拷貝

掃碼二維碼 獲取免費視頻學習資料

Python編程學習

查 看2022高級編程視頻教程免費獲取