go中for范围的表现

wjz*_*047 2 for-loop go

当遍历一个数组时,每次迭代都会返回两个值。第一个是索引,第二个是该索引处元素副本

这是我的代码:

var myArray = [5]int {1,2,3,4,5}
sum := 0
// first with copy
for _, value := range myArray {
    sum += value
}
// second without copy
for i := range myArray {
    sum += myArray[i]
}
Run Code Online (Sandbox Code Playgroud)

我应该使用哪一种以获得更好的性能?

这两段代码中的内置类型有什么区别吗?

小智 8

我们可以使用 Go 的基准测试工具对此进行测试(更多信息请访问https://dave.cheney.net/2013/06/30/how-to-write-benchmarks-in-go)。

sum_test.go

package sum

import "testing"

func BenchmarkSumIterator(b *testing.B) {
    var ints = [5]int{1, 2, 3, 4, 5}

    sum := 0
    for i := 0; i < b.N; i++ {
        for j := range ints {
            sum += ints[j]
        }
    }
}

func BenchmarkSumRange(b *testing.B) {
    var ints = [5]int{1, 2, 3, 4, 5}

    sum := 0
    for i := 0; i < b.N; i++ {
        for _, value := range ints {
            sum += value
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

运行它:

$ go test -bench=. sum_test.go 
goos: linux
goarch: amd64
BenchmarkSumIterator-4      412796047            2.97 ns/op
BenchmarkSumRange-4         413581974            2.89 ns/op
PASS
ok      command-line-arguments  3.010s
Run Code Online (Sandbox Code Playgroud)

范围似乎稍微更有效。多次运行该基准测试也证实了这一点。值得注意的是,这可能仅适用于具有小型固定大小数组的特定情况。您应该尝试根据在生产中遇到的情况做出此类决定,并尝试将其与代码可读性相协调。


Cal*_*oki 6

第二个更快,但差异太小,您可以忽略

主要区别在于当你有一个大尺寸的循环时。在这种情况下,第一个循环比第二个循环占用更多的内存