oklog / ulid

Universally Unique Lexicographically Sortable Identifier (ULID) in Go
Apache License 2.0
4.44k stars 161 forks source link

big bug: Not Sortable #90

Closed ABOB9 closed 1 year ago

ABOB9 commented 1 year ago

var count int64 func Ulid() string { return ulid.MustNew(ulid.Timestamp(time.Now()), ulid.Monotonic(rand.New(rand.NewSource(atomic.AddInt64(&count, 1))), 0)).String() }

for that,I write some testing code:

now := time.Now() id := ulid.MustNew(ulid.Timestamp(now), ulid.Monotonic(rand.New(rand.NewSource(1)), 0)) id2 := ulid.MustNew(ulid.Timestamp(now), ulid.Monotonic(rand.New(rand.NewSource(2)), 0)) fmt.Println( (id2.String() > id.String()) == true) // false if (id2.String() > id.String()) == false { t.Error("big bug") } I want to get a true, but it return a false to me.

but the following code give me a true: now := time.Now() id := ulid.MustNew(ulid.Timestamp(now), ulid.Monotonic(rand.New(rand.NewSource(99)), 0)) id2 := ulid.MustNew(ulid.Timestamp(now), ulid.Monotonic(rand.New(rand.NewSource(100)), 0)) fmt.Println( (id2.String() > id.String()) == true) // true if (id2.String() > id.String()) == false { t.Error("big bug") }

tsenart commented 1 year ago

You get true because you're using the same timestamp to generate the two ULIDs, so the only difference between them two is the random part. If you want id2 to sort after id1 even if they have the same time component, then you need to use the same Monotonic source.

Check this example: https://go.dev/play/p/ZsxbUBqef_6

ABOB9 commented 1 year ago

Thank you very very much!