如果我們要遍歷某個陣列,map集合,slice切片等,go語言(golang)為我們提供了比較好用的for range方式。range是乙個關鍵字,表示範圍,和for配合使用可以迭代陣列,map等集合。它的用法簡潔,而且map、channel等也都是用for range的方式,所以在編碼中我們使用for range
進行迴圈迭代是最多的。對於這種最常使用的迭代,尤其是和for i=0;ifor range
的使用非常簡單,這裡演示下兩種集合型別的使用。
package main
import "fmt"
func main()
for i,age:=range ages
}
這是針對 slice 切片的迭代使用,使用range
關鍵字返回兩個變數i,age
,第乙個是 slice 切片的索引,第二個是 slice 切片中的內容,所以我們列印出來:
0 10
1 20
2 30
關於go語言 slice 切片的,可以參考我以前寫的這篇 go語言實戰筆記(五)| go 切片
下面再看看map(字典)的for range
使用示例。
package main
import "fmt"
func main()
for name,age:=range ages
}
在使用for range
迭代map的時候,返回的第乙個變數是key
,第二個變數是value
,也就是我們例子中對應的name
和ages
。我們執行程式看看輸出結果。
張三 15
李四 20
王武 36
這裡需要注意的是,for range map
返回的k-v
鍵值對順序是不固定的,是隨機的,這次可能是張三-15
第乙個出現,下一次執行可能是王武-36
第乙個被列印了。
關於map更詳細的可以參考我以前的一篇文章 go語言實戰筆記(六)| go map。
比如對於 slice 切片,我們有兩種迭代方式:一種是常規的for i:=0;i為了測試,寫了這兩種迴圈迭代 slice 切片的函式,從實現上看,他們的邏輯是一樣的,保證我們可以在同樣的情況下測試。
import "testing"
const n = 1000
func initslice() string
}
現在,我們再次進行 benchmark 效能測試,看看效果。
benchmarkforslice-4 5000000 280 ns/op
benchmarkrangeforslice-4 5000000 277 ns/op
恩,和我們想的一樣,效能上來了,和常規的for迴圈持平了。原因就是我們通過_
捨棄了元素的複製,然後通過s[i]
獲取迭代的元素,既提高了效能,又達到了目的。
func rangeformap1(m map[int]string)
}const n = 1000
func initmap() map[int]string
return m
}func benchmarkrangeformap1(b *testing.b)
}
飛雪無情的部落格
以上示例是map遍歷的函式以及benchmark測試,我都寫在一起了,執行測試看一下效果。
benchmarkforslice-8 5000000 298 ns/op
benchmarkrangeforslice-8 3000000 475 ns/op
benchmarkrangeformap1-8 100000 14531 ns/op
相比 slice 來說,map的遍歷的效能更差,可以說是慘不忍睹。好,我們開始下優化,思路也是減少值得拷貝。測試中的rangeforslice也慢的原因是我把rangeforslice還原成了值得拷貝,以便於對比效能。
func rangeformap2(m map[int]string)
}func benchmarkrangeformap2(b *testing.b)
}
再次執行下效能測試看下效果。
benchmarkforslice-8 5000000 298 ns/op
benchmarkrangeforslice-8 3000000 475 ns/op
benchmarkrangeformap1-8 100000 14531 ns/op
benchmarkrangeformap2-8 100000 23199 ns/op
額,是不是發現點不對,方法benchmarkrangeformap2
的效能明顯下降了,這個可以從每次操作的耗時看出來(雖然效能測試秒執行的次數還是一樣)。和我們上面測試的slice不一樣,這次不止沒有提公升,反而下降了。
繼續修改map2
函式的實現為:
func rangeformap2(m map[int]person)
}
什麼都不做,只迭代,再次執行效能測試。
benchmarkforslice-8 5000000 301 ns/op
benchmarkrangeforslice-8 3000000 478 ns/op
benchmarkrangeformap1-8 100000 14822 ns/op
benchmarkrangeformap2-8 100000 14215 ns/op
*我們驚奇的發現,什麼都不做,和獲取k-v
值的操作效能是一樣的,和slice完全不一樣,不是說for range
值拷貝損耗效能呢?都哪去了?大家猜一猜,可以結合下一節的原理實現通過檢視源**,我們可以發現for range
的實現是:
// for init ; cond ; post
並且對於slice,map等各有具體不同的編譯實現,我們先看看for range slice
的具體實現
// the loop we generate:
// for_temp := range
// len_temp := len(for_temp)
// for index_temp = 0; index_temp < len_temp; index_temp++
先是對要遍歷的 slice 做乙個拷貝,獲取長度大小,然後使用常規for
迴圈進行遍歷,並且返回值的拷貝。
再看看for range map
的具體實現:
// the loop we generate:
// var hiter map_iteration_struct
// for mapiterinit(type, range, &hiter); hiter.key != nil; mapiternext(&hiter)
也是先對map
進行了初始化,因為map
是*hashmap
,所以這裡其實是乙個*hashmap
指標的拷貝。
flysnow_org
或者**
C語言效能優化
1 資料型別 1 如果確定整數非負,應直接使用unsigned int,處理器處理無符號unsigned 整形數的效率遠遠高於有符號signed整形數 2 float可以用int替代,如果需要結果精確到小數點後n位,可以將其乘以n 10,結果盡可能晚的把它轉換為浮點型數字 3 區域性變數盡可能的不使...
從Baa開發中總結Go語言效能漸進優化
在go生態已經有很多web框架,但感覺沒有乙個符合我們的想法,我們想要乙個簡潔高效的核心框架,提供路由,context,中介軟體和依賴注入,而且拒絕使用正則和反射,於是我們開始構建baa框架。一開始使用最簡單的通俗寫法實現了第一版的功能,基本可用,但是效能爛到爆,優化之路漫漫開啟。最好的文章應該是每...
C語言效能優化 使用位運算
使用位操作可以減少除法和取模的運算。在電腦程式中資料的位是可以操作的最小資料單位,理論上可以用 位運算 來完成所有的運算和操作。一般的位操作是用來控制硬體的,或者進行資料變換,但是,靈活的位操作可以有效地提高程式執行的效率。例如 方法g int i,j i 257 8 j 456 32 方法h in...