1. 数组的遍历

数组和切片的遍历方式一样,所以我们这里就不进行区分。

我们一般用以下两种方式

  • 直接取下标方式
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)