github.com/wfusion/gofusion@v1.1.14/common/utils/random.go (about) 1 package utils 2 3 import ( 4 cryptoRand "crypto/rand" 5 "encoding/ascii85" 6 "encoding/base64" 7 "encoding/hex" 8 "math/rand" 9 "reflect" 10 "strconv" 11 "strings" 12 "time" 13 14 "github.com/google/uuid" 15 "github.com/lithammer/shortuuid/v4" 16 "github.com/oklog/ulid/v2" 17 18 "github.com/wfusion/gofusion/common/constant" 19 "github.com/wfusion/gofusion/common/utils/inspect" 20 ) 21 22 func UUID() string { 23 return uuid.New().String() 24 } 25 26 // UUID_ 27 //nolint: revive // uuid without hyphen function issue 28 func UUID_() string { 29 return strings.Replace(uuid.New().String(), constant.Hyphen, "", -1) 30 } 31 32 // ShortUUID returns a new short UUID with base57 33 func ShortUUID() string { 34 return shortuuid.New() 35 } 36 37 // ULID returns a new ULID. 38 func ULID() string { 39 return ulid.MustNew(ulid.Now(), cryptoRand.Reader).String() 40 } 41 42 func UUID20() string { 43 id := uuid.New() 44 t := make([]byte, ascii85.MaxEncodedLen(len(id))) 45 n := ascii85.Encode(t, id[:]) 46 return string(t[:n]) 47 } 48 49 func UUID22() string { 50 id := uuid.New() 51 return base64.RawURLEncoding.EncodeToString(id[:]) 52 } 53 54 const ( 55 randomChars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" 56 randomCharsLength = len(randomChars) 57 ) 58 59 func CryptoRandom(b []byte) (n int, err error) { 60 return cryptoRand.Read(b) 61 } 62 63 func CryptoRandomBytes(size int) ([]byte, error) { 64 b := make([]byte, size) 65 if _, err := cryptoRand.Read(b); err != nil { 66 return nil, err 67 } 68 return b, nil 69 } 70 71 func CryptoRandomLetterAndNumber(n int) (string, error) { 72 b, err := CryptoRandomBytes(n) 73 if err != nil { 74 return "", err 75 } 76 77 random := make([]byte, 0, n) 78 for i := 0; i < n; i++ { 79 random = append(random, randomChars[b[i]%uint8(randomCharsLength)]) 80 } 81 return string(random), nil 82 } 83 84 func RandomLetterAndNumber(n int) string { 85 random := make([]byte, 0, n) 86 rand.Seed(time.Now().UnixNano()) 87 for i := 0; i < n; i++ { 88 random = append(random, randomChars[rand.Intn(randomCharsLength)]) 89 } 90 91 return string(random) 92 } 93 94 func Random(b []byte, seed int64) (n int, err error) { 95 if seed == 0 { 96 rand.Seed(time.Now().UnixNano()) 97 } else { 98 rand.Seed(seed) 99 } 100 return rand.Read(b) 101 } 102 103 func RandomNumbers(n int) string { 104 rand.Seed(time.Now().UnixNano()) 105 ret := "" 106 for i := 0; i < n; i++ { 107 ret += strconv.Itoa(rand.Intn(10)) 108 } 109 return ret 110 } 111 112 func CryptoRandomNumbers(n int) (string, error) { 113 b, err := CryptoRandomBytes(n) 114 if err != nil { 115 return "", err 116 } 117 118 random := make([]byte, 0, n) 119 for i := 0; i < n; i++ { 120 random = append(random, randomChars[b[i]%uint8(10)]) 121 } 122 return string(random), nil 123 } 124 125 func NginxID() string { 126 upper := func(c byte) byte { 127 val := c 128 if val >= 97 && val <= 122 { 129 return val - 32 130 } 131 return c 132 } 133 int2byte := func(bs []byte, val int) { 134 size := 10 135 l := len(bs) - 1 136 for idx := l; idx >= 0; idx-- { 137 bs[idx] = byte(uint(val%size) + uint('0')) 138 val = val / size 139 } 140 } 141 142 ret := [33]byte{} 143 t := time.Now() 144 year, month, day := t.Date() 145 hour, minute, second := t.Clock() 146 int2byte(ret[:4], year) 147 int2byte(ret[4:6], int(month)) 148 int2byte(ret[6:8], day) 149 int2byte(ret[8:10], hour) 150 int2byte(ret[10:12], minute) 151 int2byte(ret[12:14], second) 152 copy(ret[14:26], LocalIP.Bytes()) 153 ms := t.UnixNano() / 1e6 % 1000 154 int2byte(ret[26:29], int(ms)) 155 u32 := rand.Uint32() 156 u32 >>= 16 157 src := []byte{byte(u32 & 0xff), byte((u32 >> 8) & 0xff)} 158 hex.Encode(ret[29:33], src) 159 for idx := 29; idx < 33; idx++ { 160 ret[idx] = upper(ret[idx]) 161 } 162 return string(ret[:]) 163 } 164 165 func NewSafeRand(seed int64) *rand.Rand { 166 return rand.New(newBuiltinLockedSource(seed)) 167 } 168 169 func newBuiltinLockedSource(seed int64) rand.Source64 { 170 t := inspect.TypeOf("math/rand.lockedSource") 171 source := reflect.New(t).Interface() 172 173 var err error 174 IfAny( 175 // go1.16 - go1.19 176 func() bool { 177 _, err = Catch(func() { inspect.SetField(source, "src", rand.NewSource(seed)) }) 178 return err == nil 179 }, 180 // go1.20 - go1.21, source is renamed and set seed when calling rather than constructing stage 181 func() bool { 182 _, err = Catch(func() { inspect.SetField(source, "s", rand.NewSource(seed)) }) 183 return err == nil 184 }, 185 ) 186 if err != nil { 187 panic(err) 188 } 189 190 return source.(rand.Source64) 191 } 192 193 func init() { 194 rand.Seed(time.Now().Unix()) 195 196 // assert if rand.lockedSource struct is not changed 197 newBuiltinLockedSource(1).Int63() 198 }