github.com/gogf/gf/v2@v2.7.4/util/grand/grand.go (about) 1 // Copyright GoFrame Author(https://goframe.org). All Rights Reserved. 2 // 3 // This Source Code Form is subject to the terms of the MIT License. 4 // If a copy of the MIT was not distributed with this file, 5 // You can obtain one at https://github.com/gogf/gf. 6 7 // Package grand provides high performance random bytes/number/string generation functionality. 8 package grand 9 10 import ( 11 "encoding/binary" 12 "time" 13 ) 14 15 var ( 16 letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" // 52 17 symbols = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~" // 32 18 digits = "0123456789" // 10 19 characters = letters + digits + symbols // 94 20 ) 21 22 // Intn returns an int number which is between 0 and max: [0, max). 23 // 24 // Note that: 25 // 1. The `max` can only be greater than 0, or else it returns `max` directly; 26 // 2. The result is greater than or equal to 0, but less than `max`; 27 // 3. The result number is 32bit and less than math.MaxUint32. 28 func Intn(max int) int { 29 if max <= 0 { 30 return max 31 } 32 n := int(binary.LittleEndian.Uint32(<-bufferChan)) % max 33 if (max > 0 && n < 0) || (max < 0 && n > 0) { 34 return -n 35 } 36 return n 37 } 38 39 // B retrieves and returns random bytes of given length `n`. 40 func B(n int) []byte { 41 if n <= 0 { 42 return nil 43 } 44 i := 0 45 b := make([]byte, n) 46 for { 47 copy(b[i:], <-bufferChan) 48 i += 4 49 if i >= n { 50 break 51 } 52 } 53 return b 54 } 55 56 // N returns a random int between min and max: [min, max]. 57 // The `min` and `max` also support negative numbers. 58 func N(min, max int) int { 59 if min >= max { 60 return min 61 } 62 if min >= 0 { 63 return Intn(max-min+1) + min 64 } 65 // As `Intn` dose not support negative number, 66 // so we should first shift the value to right, 67 // then call `Intn` to produce the random number, 68 // and finally shift the result back to left. 69 return Intn(max+(0-min)+1) - (0 - min) 70 } 71 72 // S returns a random string which contains digits and letters, and its length is `n`. 73 // The optional parameter `symbols` specifies whether the result could contain symbols, 74 // which is false in default. 75 func S(n int, symbols ...bool) string { 76 if n <= 0 { 77 return "" 78 } 79 var ( 80 b = make([]byte, n) 81 numberBytes = B(n) 82 ) 83 for i := range b { 84 if len(symbols) > 0 && symbols[0] { 85 b[i] = characters[numberBytes[i]%94] 86 } else { 87 b[i] = characters[numberBytes[i]%62] 88 } 89 } 90 return string(b) 91 } 92 93 // D returns a random time.Duration between min and max: [min, max]. 94 func D(min, max time.Duration) time.Duration { 95 multiple := int64(1) 96 if min != 0 { 97 for min%10 == 0 { 98 multiple *= 10 99 min /= 10 100 max /= 10 101 } 102 } 103 n := int64(N(int(min), int(max))) 104 return time.Duration(n * multiple) 105 } 106 107 // Str randomly picks and returns `n` count of chars from given string `s`. 108 // It also supports unicode string like Chinese/Russian/Japanese, etc. 109 func Str(s string, n int) string { 110 if n <= 0 { 111 return "" 112 } 113 var ( 114 b = make([]rune, n) 115 runes = []rune(s) 116 ) 117 if len(runes) <= 255 { 118 numberBytes := B(n) 119 for i := range b { 120 b[i] = runes[int(numberBytes[i])%len(runes)] 121 } 122 } else { 123 for i := range b { 124 b[i] = runes[Intn(len(runes))] 125 } 126 } 127 return string(b) 128 } 129 130 // Digits returns a random string which contains only digits, and its length is `n`. 131 func Digits(n int) string { 132 if n <= 0 { 133 return "" 134 } 135 var ( 136 b = make([]byte, n) 137 numberBytes = B(n) 138 ) 139 for i := range b { 140 b[i] = digits[numberBytes[i]%10] 141 } 142 return string(b) 143 } 144 145 // Letters returns a random string which contains only letters, and its length is `n`. 146 func Letters(n int) string { 147 if n <= 0 { 148 return "" 149 } 150 var ( 151 b = make([]byte, n) 152 numberBytes = B(n) 153 ) 154 for i := range b { 155 b[i] = letters[numberBytes[i]%52] 156 } 157 return string(b) 158 } 159 160 // Symbols returns a random string which contains only symbols, and its length is `n`. 161 func Symbols(n int) string { 162 if n <= 0 { 163 return "" 164 } 165 var ( 166 b = make([]byte, n) 167 numberBytes = B(n) 168 ) 169 for i := range b { 170 b[i] = symbols[numberBytes[i]%32] 171 } 172 return string(b) 173 } 174 175 // Perm returns, as a slice of n int numbers, a pseudo-random permutation of the integers [0,n). 176 // TODO performance improving for large slice producing. 177 func Perm(n int) []int { 178 m := make([]int, n) 179 for i := 0; i < n; i++ { 180 j := Intn(i + 1) 181 m[i] = m[j] 182 m[j] = i 183 } 184 return m 185 } 186 187 // Meet randomly calculate whether the given probability `num`/`total` is met. 188 func Meet(num, total int) bool { 189 return Intn(total) < num 190 } 191 192 // MeetProb randomly calculate whether the given probability is met. 193 func MeetProb(prob float32) bool { 194 return Intn(1e7) < int(prob*1e7) 195 }