Skip to content

Revisiting is.Equal and the role of reflect.DeepEqual #53

@willbicks

Description

@willbicks

I started switching from google/go-cmp to is in pursuit of the latter's more pleasant and succinct syntax, but unfortunately have run into issues with how times are compared by is.

In the code being tested, a time is created using time.Now(), stored to a database, and then later retrieved. When comparing the two times (or the structs containing time values), is.Equal reports that the times are different because one has a monotonic counter and the other does not. This differs from how the standard library time.Equal() functions, which is recommend by the Go team instead of directly comparing time values.

For example, consider the following excerpt where time1 has a monotonic counter, and time2 is the same time without a monotonic counter:

time1 := time.Now()
time2 := time1.Round(0) // returns time1 stripped of any monotonic clock reading but otherwise unchanged (see https://pkg.go.dev/time#Time.Round)
fmt.Printf("time1.Equal(time2) = %v\n", time1.Equal(time2))
is.Equal(time1, time2)

which results in the following:

time1.Equal(time2) = true
test.go:25: 2023-03-10 19:18:46.3692787 -0500 EST m=+0.083328801 != 2023-03-10 19:18:46.3692787 -0500 EST

Is there a better way to handle these comparisons in is? Some options I can imagine include:

  1. Switch to using time.Equal() if the values being compared are times.
  2. Adopting a model similar to google/go-cmp where all "Types that have an Equal method may use that method to determine equality".
  3. Use the tried-and-true google/go-cmp library itself to perform underlying equality comparisons.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions