ulid/examples/interesting/main.go

86 lines
1.7 KiB
Go

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)
}