From acbb2c31ea729bb6854659140c6c79ced1f5eab9 Mon Sep 17 00:00:00 2001 From: Tony Holdstock-Brown Date: Sat, 10 Feb 2024 12:20:46 -0800 Subject: [PATCH] Add `uuid.Nil` and `.IsZero()` method This simplifies comparisons with empty ULIDs. Right now, most people are doing something like the following to check if a ULID is non-zero: ```go id.Compare(ulid.ULID{}) == 0 ``` This requires allocating a new empty ULID each time. Some packages avoid this by creating their own global (or private) nil ULIDs on initialization. This should be built in and simple for better perf & a cleaner API. --- ulid.go | 8 ++++++++ ulid_test.go | 14 ++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/ulid.go b/ulid.go index 2064dd4..2f3e8b9 100644 --- a/ulid.go +++ b/ulid.go @@ -75,6 +75,9 @@ var ( // ErrScanValue is returned when the value passed to scan cannot be unmarshaled // into the ULID. ErrScanValue = errors.New("ulid: source value must be a string or byte slice") + + // Nil is an empty ULID, all zeros, useful when comparing nil ULIDs + Nil ULID ) // MonotonicReader is an interface that should yield monotonically increasing @@ -416,6 +419,11 @@ func (id ULID) Timestamp() time.Time { return Time(id.Time()) } +// IsZero returns whether the ULID is a zero-value, ie ulid.Nil. +func (id ULID) IsZero() bool { + return bytes.Compare(id[:], Nil[:]) == 0 +} + // maxTime is the maximum Unix time in milliseconds that can be // represented in a ULID. var maxTime = ULID{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}.Time() diff --git a/ulid_test.go b/ulid_test.go index 43f81c6..510d111 100644 --- a/ulid_test.go +++ b/ulid_test.go @@ -454,6 +454,20 @@ func TestULIDTimestamp(t *testing.T) { } } +func TestZero(t *testing.T) { + t.Parallel() + + var id ulid.ULID + if ok := id.IsZero(); !ok { + t.Error(".IsZero: must return true for empty ULIDs, have false") + } + + id = ulid.MustNew(ulid.Now(), ulid.DefaultEntropy()) + if ok := id.IsZero(); ok { + t.Error(".IsZero: must return false for non-nil ULIDs, have true") + } +} + func TestEntropy(t *testing.T) { t.Parallel()