這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
轉載自達達的部落格
以往的C編程經驗告訴我們,指標傳參會有更好的效能,在Go語言中,這條經驗也是通用的。但是需要留意兩個問題:
- 指標傳參會導致參數的操作領域不確定,到底函數內部會不會改變傳入的對象呢?Go語言中沒有類型C那樣的const關鍵字,所以無法控制。
- Go語言是有GC的,並且這個GC還不是很完善,受對象數量影響較大,傳遞指標意味著可能多建立不必要的對象,到底指標傳參帶來的效能提升能不能抵消建立對象產生的GC壓力呢?這是一個不好觀察到的資料。(原作者達達這裡應該是有錯誤的,首先傳值也是複製,要產生一個新對象,分配記憶體位址傳到新的函數中,其次指標一般來說64個位元組,複製的代價遠小大中型資料傳值,因此在都產生一個新對象的情況下,指標還是遠優先於傳大中型的值結構)
下面是效能消耗的測試代碼:
package labs02import "testing"type BigStruct struct { C01 uint64 C02 uint64 C03 uint64 C04 uint64 C05 uint64 C06 uint64 C07 uint64 C08 uint64 C09 uint64 C10 uint64 C11 uint64 C12 uint64 C13 uint64 C14 uint64 C15 uint64 C16 uint64 C17 uint64 C18 uint64 C19 uint64 C20 uint64 C21 uint64 C22 uint64 C23 uint64 C24 uint64 C25 uint64 C26 uint64 C27 uint64 C28 uint64 C29 uint64 C30 uint64}func Invoke1(a *BigStruct) uint64 { return a.C30}func Invoke2(a BigStruct) uint64 { return a.C30}func Benchmark_Invoke1(b *testing.B) { var a = new(BigStruct) for i := 0; i < b.N; i++ { Invoke1(a) }}func Benchmark_Invoke2(b *testing.B) { var a = BigStruct{} for i := 0; i < b.N; i++ { Invoke2(a) }}
測試值傳參和指標傳參的效率。
實驗結果:
dada-imac:misc dada$ go test -test.bench="." labs02testing: warning: no tests to runPASSBenchmark_Invoke1 2000000000 0.52 ns/opBenchmark_Invoke2 100000000 12.8 ns/opok labs02 2.403s