Add examples
parent
91b8b60e16
commit
db84ce0456
|
@ -0,0 +1,85 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
crypto "crypto/rand"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"git.wisellama.rocks/Wisellama/ulid"
|
||||
)
|
||||
|
||||
func main() {
|
||||
t := time.Now()
|
||||
|
||||
entropy, err := interestingEntropy()
|
||||
if err != nil {
|
||||
fmt.Printf("error creating entropy source: %v\n", err)
|
||||
}
|
||||
|
||||
wg := sync.WaitGroup{}
|
||||
for i := 0; i < 30; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
u, err := ulid.NewULIDString(t, entropy)
|
||||
if err != nil {
|
||||
fmt.Printf("error: %v\n", err)
|
||||
}
|
||||
|
||||
fmt.Printf("ULID: %s\n", u)
|
||||
}()
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
fmt.Printf("Done\n")
|
||||
}
|
||||
|
||||
// interestingEntropy returns a psuedo random source. This is an
|
||||
// alternative to always using crypto/rand and potentially running out
|
||||
// of entropy. Don't rely on this for security-sensitive applications.
|
||||
//
|
||||
// It uses crypto/rand to get the seed for a math/rand psuedorandom
|
||||
// number generator. This way we don't collide with other instances
|
||||
// that might start at the same time.
|
||||
//
|
||||
// It also uses a simple locked source for concurrency. If you want a
|
||||
// more official implementation, look at exp/rand LockedSource:
|
||||
//
|
||||
// https://pkg.go.dev/golang.org/x/exp/rand#LockedSource
|
||||
func interestingEntropy() (*rand.Rand, error) {
|
||||
seedBytes := make([]byte, 8)
|
||||
_, err := crypto.Read(seedBytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
seedInt, _ := binary.Varint(seedBytes)
|
||||
|
||||
source := &LockedSource{
|
||||
Source: rand.NewSource(seedInt),
|
||||
}
|
||||
|
||||
// nolint
|
||||
return rand.New(source), nil
|
||||
|
||||
}
|
||||
|
||||
type LockedSource struct {
|
||||
mx sync.Mutex
|
||||
Source rand.Source
|
||||
}
|
||||
|
||||
func (s *LockedSource) Int63() int64 {
|
||||
s.mx.Lock()
|
||||
defer s.mx.Unlock()
|
||||
return s.Source.Int63()
|
||||
}
|
||||
|
||||
func (s *LockedSource) Seed(seed int64) {
|
||||
s.mx.Lock()
|
||||
defer s.mx.Unlock()
|
||||
s.Source.Seed(seed)
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"git.wisellama.rocks/Wisellama/ulid"
|
||||
)
|
||||
|
||||
func main() {
|
||||
t := time.Now()
|
||||
// This example uses the crypto/rand entropy. This is thread safe
|
||||
// and intended to be used for secure features. If you are using
|
||||
// ULIDs for anything related to security/authentication, then use
|
||||
// this entropy source.
|
||||
u, err := ulid.NewULIDString(t, rand.Reader)
|
||||
if err != nil {
|
||||
fmt.Printf("error: %v\n", err)
|
||||
}
|
||||
|
||||
fmt.Printf("ULID: %s\n", u)
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
"git.wisellama.rocks/Wisellama/ulid"
|
||||
)
|
||||
|
||||
func main() {
|
||||
t := time.Now()
|
||||
|
||||
// Warning: Using time.Now() for the entropy seed is bad if you
|
||||
// have multiple instances all starting up at the same time who
|
||||
// might write to the same data store.
|
||||
//
|
||||
// The default rand.NewSource() is also bad for multiple
|
||||
// threads. You either need to implement your own locking
|
||||
// mechanism or use a LockedSource:
|
||||
// https://pkg.go.dev/golang.org/x/exp/rand#LockedSource
|
||||
//
|
||||
// See the other examples for better alternatives.
|
||||
//
|
||||
// nolint
|
||||
entropy := rand.New(rand.NewSource(t.UnixMilli()))
|
||||
|
||||
u, err := ulid.NewULIDString(t, entropy)
|
||||
if err != nil {
|
||||
fmt.Printf("error: %v\n", err)
|
||||
}
|
||||
|
||||
fmt.Printf("ULID: %s\n", u)
|
||||
}
|
17
ulid_test.go
17
ulid_test.go
|
@ -9,6 +9,11 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
func getTestRandomSource() *rand.Rand {
|
||||
// nolint
|
||||
return rand.New(rand.NewSource(0))
|
||||
}
|
||||
|
||||
func TestGetMSBytes(t *testing.T) {
|
||||
runAll := true
|
||||
|
||||
|
@ -102,7 +107,7 @@ func TestNewULID(t *testing.T) {
|
|||
TestName: "Unix zero time",
|
||||
RunIt: false || runAll,
|
||||
Time: time.Unix(0, 0),
|
||||
Entropy: rand.New(rand.NewSource(0)),
|
||||
Entropy: getTestRandomSource(),
|
||||
Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x94, 0xFD, 0xC2, 0xFA, 0x2F, 0xFC, 0xC0, 0x41, 0xD3},
|
||||
Err: false,
|
||||
},
|
||||
|
@ -110,7 +115,7 @@ func TestNewULID(t *testing.T) {
|
|||
TestName: "time overflow",
|
||||
RunIt: false || runAll,
|
||||
Time: time.Time{}, // zero time overflows when using Unix epoch time
|
||||
Entropy: rand.New(rand.NewSource(0)),
|
||||
Entropy: getTestRandomSource(),
|
||||
Expected: nil,
|
||||
Err: true,
|
||||
},
|
||||
|
@ -118,7 +123,7 @@ func TestNewULID(t *testing.T) {
|
|||
TestName: "seed 0, real time",
|
||||
RunIt: false || runAll,
|
||||
Time: time.Date(2024, 02, 16, 14, 02, 15, 17, time.UTC),
|
||||
Entropy: rand.New(rand.NewSource(0)),
|
||||
Entropy: getTestRandomSource(),
|
||||
Expected: []byte{0x01, 0x8D, 0xB2, 0x39, 0x96, 0x58, 0x01, 0x94, 0xFD, 0xC2, 0xFA, 0x2F, 0xFC, 0xC0, 0x41, 0xD3},
|
||||
Err: false,
|
||||
},
|
||||
|
@ -175,7 +180,7 @@ func TestULIDString(t *testing.T) {
|
|||
TestName: "Unix zero time",
|
||||
RunIt: false || runAll,
|
||||
Time: time.Unix(0, 0),
|
||||
Entropy: rand.New(rand.NewSource(0)),
|
||||
Entropy: getTestRandomSource(),
|
||||
Expected: "000000000006AFVGQT5ZYC0GEK",
|
||||
Err: false,
|
||||
},
|
||||
|
@ -183,7 +188,7 @@ func TestULIDString(t *testing.T) {
|
|||
TestName: "time overflow",
|
||||
RunIt: false || runAll,
|
||||
Time: time.Time{}, // zero time overflows when using Unix epoch time
|
||||
Entropy: rand.New(rand.NewSource(0)),
|
||||
Entropy: getTestRandomSource(),
|
||||
Expected: "",
|
||||
Err: true,
|
||||
},
|
||||
|
@ -191,7 +196,7 @@ func TestULIDString(t *testing.T) {
|
|||
TestName: "seed 0, real time",
|
||||
RunIt: false || runAll,
|
||||
Time: time.Date(2024, 02, 16, 14, 02, 15, 17, time.UTC),
|
||||
Entropy: rand.New(rand.NewSource(0)),
|
||||
Entropy: getTestRandomSource(),
|
||||
Expected: "01HPS3K5JR06AFVGQT5ZYC0GEK",
|
||||
Err: false,
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue