Writing a thorough comparison of a compound type’s two instances can be verbose. While you can use reflect.DeepEqual to compare structs, maps, and slices, there’s a better way. Back in 2017, Google released a third-party module called go-cmp that does the comparison for you and returns a detailed description of what does not match. Let’s see how it works by defining a simple struct and a factory function that populates it. You can find this code in the examples/cmp directory:
type Person struct {
Name string
Age int
DateAdded time.Time
}
func CreatePerson(name string, age int) Person {
return Person{
Name: name,
Age: age,
DateAdded: time.Now(),
}
}
In your test file, import github.com/google/go-cmp/cmp. The test function looks like this:
func TestCreatePerson(t *testing.T) {
expected := Person{
Name: "Dennis",
Age: 37,
}
result := CreatePerson("Dennis", 37)
if diff := cmp.Diff(expected, result); diff != "" {
t.Error(diff)
}
}
The cmp.Diff function takes in the expected output and the output that was returned by the function that you’re testing. It returns a string that describes any mismatches between the two inputs. If the inputs match, it returns an empty string. You assign the output of the cmp.Diff function to a variable called diff and then check whether diff is an empty string. If it is not, an error occurred.
When you build and run the test, you’ll see the output that go-cmp generates when two struct instances don’t match:
$ go test
--- FAIL: TestCreatePerson (0.00s)
ch13_cmp_test.go:16: ch13_cmp.Person{
Name: "Dennis",
Age: 37,
- DateAdded: s"0001-01-01 00:00:00 +0000 UTC",
+ DateAdded: s"2020-03-01 22:53:58.087229 -0500 EST m=+0.001242842",
}
FAIL
FAIL ch13_cmp 0.006s
The lines with a - and + indicate the fields whose values differ. The test failed because the dates didn’t match. This is a problem because you can’t control what date the CreatePerson function assigns. You have to ignore the DateAdded field. The go-cmp module includes a helper package, cmpopts, which contains functions that provide additional control over the comparisons performed by cmp.Diff. In this case, use cmpopts.IgnoreFields to (unsurprisingly) ignore a field:
if diff := cmp.Diff(expected,
result,
cmpopts.IgnoreFields(Person{}, "DateAdded")); diff != "" {
t.Error(diff)
}
This is only a quick preview of the most useful features in go-cmp. Check its documentation to learn more about how to control what is compared and the output format.