如果有一些不重复的数据需要记录,并且用来查询某一数据是否存在,可以有两种做法:
1、存在slice中,每次查询时遍历slice,如果查到数据则退出遍历,时间复杂度是O(n)。
2、存在一个集合中,golang中可以使用map的key来保存,每次直接判断该数据是否存在,时间复杂度是O(1)。

从时间复杂度上面来看,使用map是有明显优势的,但是如果数据量较小,O(1)可能并没有O(n)的速度快,那么应该如何选择呢?
下面写了一个性能测试:

package main

import (
	"testing"
)

var s []int
var m map[int]struct{}

func init() {
	num := 10
	s = make([]int, num)
	m = make(map[int]struct{}, num)
	for i := 0; i < num; i++ {
		s[i] = i
		m[i] = struct{}{}
	}
}

func BenchmarkSlice(b *testing.B) {
	size := len(s)
	for i := 0; i < b.N; i++ {
		n := i % size
		for k := 0; k < len(s); k++ {
			if s[k] == n {
				break
			}
		}
	}
}

func BenchmarkMap(b *testing.B) {
	size := len(s)
	for i := 0; i < b.N; i++ {
		n := i % size
		_ = m[n]
	}
}

测试结果:
num = 1:
BenchmarkSlice-4 200000000 9.20 ns/op
BenchmarkMap-4 100000000 15.3 ns/op

num = 10:
BenchmarkSlice-4 100000000 11.2 ns/op
BenchmarkMap-4 100000000 16.7 ns/op

num = 20:
BenchmarkSlice-4 100000000 14.9 ns/op
BenchmarkMap-4 100000000 16.7 ns/op

num = 30:
BenchmarkSlice-4 100000000 18.9 ns/op
BenchmarkMap-4 100000000 16.8 ns/op

num = 100:
BenchmarkSlice-4 50000000 40.0 ns/op
BenchmarkMap-4 100000000 17.7 ns/op

根据测试结果可以发现,map随着数据量的增多,对性能产生的影响比较小,在大量数据的情况下性能有明显优势,在无法估计数据量的情况下,map的适用范围更广。如果是性能关键点并且数据量较小,可以考虑使用slice。