我有一个像这样的表驱动测试用例:
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{}