我有一个像这样的表驱动测试用例:
func CountWords(s string) map[string]int func TestCountWords(t *testing.T) { var tests = []struct { input string want map[string]int }{ {"foo", map[string]int{"foo":1}}, {"foo bar foo", map[string]int{"foo":2,"bar":1}}, } for i, c := range tests { got := CountWords(c.input) // TODO test whether c.want == got } }
我可以检查长度是否相同,并编写一个循环来检查每个键值对是否相同。但是,当我想将其用于另一种类型的地图(例如map[string]string)时,必须再次编写此检查。
map[string]string
我最终要做的是,将地图转换为字符串并比较了字符串:
func checkAsStrings(a,b interface{}) bool { return fmt.Sprintf("%v", a) != fmt.Sprintf("%v", b) } //... if checkAsStrings(got, c.want) { t.Errorf("Case #%v: Wanted: %v, got: %v", i, c.want, got) }
假定等效映射的字符串表示形式相同,在这种情况下,这似乎是正确的(如果键相同,则它们会散列为相同的值,因此它们的顺序将相同)。有一个更好的方法吗?在表驱动测试中比较两个映射的惯用方式是什么?
Go库已经覆盖了您。做这个:
import "reflect" // m1 and m2 are the maps we want to compare eq := reflect.DeepEqual(m1, m2) if eq { fmt.Println("They're equal.") } else { fmt.Println("They're unequal.") }
如果你看一下源代码供reflect.DeepEqual的Map情况下,你会发现,如果两个地图它首先检查是零,那么检查之前,他们具有相同的长度最后检查,看看他们是否有相同的一组(键,值)对。
reflect.DeepEqual
Map
由于reflect.DeepEqual采用接口类型,因此可以在任何有效的地图(map[string]bool, map[struct{}]interface{},等)上使用。请注意,它也适用于非地图值,因此请注意,传递给它的实际上是两个地图。如果您传递两个整数,它将很高兴地告诉您它们是否相等。
map[string]bool, map[struct{}]interface{}