数组和切片的遍历方式一样,所以我们这里就不进行区分。
我们一般用以下两种方式
- 直接取下标方式
for i:=0;i<len(nums);i++{
...
}
我们先来讲一下这种方式,我们都知道数组在内存中存储是连续的。所以我们直接用下表取出数组中的元素,就是直接在数组的原地址中获取,这种写法比较像c语言的写法。所以这种方式是非常快的。
- range 遍历方式
for index,item := range items{
...
}
性能是有所降低的。
benchmark测试
下面的这一段测试逻辑就是将三种遍历的方式进行 benchmark 测试,事先进行赋值并转化成字符串,然后再进行相同的操作,将字符串进行拼接。
string.builder
/*
100000
BenchmarkByRange
BenchmarkByRange-8 763 1393727 ns/op
BenchmarkByIndex
BenchmarkByIndex-8 1503 1194054 ns/op
BenchmarkByIndexAndLen
BenchmarkByIndexAndLen-8 1818 745112 ns/op
*/
func BenchmarkByRange(b *testing.B) {
elems := make([]string, 100000, 100000)
for i := 0; i < 100000; i++ {
elems[i] = strconv.Itoa(i)
}
var builder strings.Builder
b.ResetTimer()
for i := 0; i < b.N; i++ {
for _, elem := range elems {
builder.WriteString(elem)
}
}
b.StopTimer()
}
func BenchmarkByIndex(b *testing.B) {
elems := make([]string, 100000, 100000)
for i := 0; i < 100000; i++ {
elems[i] = strconv.Itoa(i)
}
var builder strings.Builder
b.ResetTimer()
for i := 0; i < b.N; i++ {
for j := 0; j < len(elems); j++ {
builder.WriteString(elems[j])
}
}
b.StopTimer()
}
func BenchmarkByIndexAndLen(b *testing.B) {
elems := make([]string, 100000, 100000)
for i := 0; i < 100000; i++ {
elems[i] = strconv.Itoa(i)
}
length := len(elems)
var builder strings.Builder
b.ResetTimer()
for i := 0; i < b.N; i++ {
for j := 0; j < length; j++ {
builder.WriteString(elems[j])
}
}
b.StopTimer()
}
在上面的测试代码中,我们可以看出,第二种是要比第一种性能稍微高了一点。
len(nums)