rand.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. // Copyright 2019 github.com. All rights reserved.
  2. // Use of this source code is governed by github.com.
  3. package util
  4. import (
  5. "math/rand"
  6. "time"
  7. )
  8. const (
  9. alpha = "abcdefghijklmnopqrstuvwyxzABCDEFGHIJKLMNOPQRSTUVWYXZ" // 字母
  10. number = "1234567890" // 数字
  11. punctuation = "!@#$%^&*()_+[]{};':\",./<>?" // 符号
  12. alphaNumber = number + alpha // 字母+数字
  13. alphaNumberPunctuation = alphaNumber + punctuation // 字母+数字+符号
  14. )
  15. // 提供几种常见的随机字符组合方式
  16. var (
  17. bytesAlpha = []byte(alpha)
  18. bytesNumber = []byte(number)
  19. bytesPunctuation = []byte(punctuation)
  20. bytesAlphaNumber = []byte(alphaNumber)
  21. bytesAlphaNumberPunctuation = []byte(alphaNumberPunctuation)
  22. )
  23. // 供全局函数使用的随机函数生成。
  24. // RandBytes 和 String 依赖此项。
  25. var random = rand.New(rand.NewSource(time.Now().UnixNano()))
  26. // RandAlpha 产生随机字母串
  27. func RandAlpha(min, max int) string {
  28. return string(RandBytes(min, max, bytesAlpha))
  29. }
  30. // RandNumber 产生随机数字串
  31. func RandNumber(min, max int) string {
  32. return string(RandBytes(min, max, bytesNumber))
  33. }
  34. // RandPunctuation 产生随机符号串
  35. func RandPunctuation(min, max int) string {
  36. return string(RandBytes(min, max, bytesPunctuation))
  37. }
  38. // RandAlphaNumber 产生随机字母+数字组合串
  39. func RandAlphaNumber(min, max int) string {
  40. return string(RandBytes(min, max, bytesAlphaNumber))
  41. }
  42. // RandAlphaNumberPunctuation 产生随机字母+数字组合串
  43. func RandAlphaNumberPunctuation(min, max int) string {
  44. return string(RandBytes(min, max, bytesAlphaNumberPunctuation))
  45. }
  46. // Seed 手动指定一个随机种子,默认情况下使用当前包初始化时的时间戳作为随机种子。
  47. // RandBytes 和 String 依赖此项。但是 Rands 有专门的随机函数,不受此影响。
  48. func Seed(seed int64) {
  49. random = rand.New(rand.NewSource(seed))
  50. }
  51. // RandBytes 产生随机字符数组,其长度为[min, max)。
  52. // bs 所有的随机字符串从此处取。
  53. func RandBytes(min, max int, bs []byte) []byte {
  54. checkArgs(min, max, bs)
  55. return genBytes(random, min+random.Intn(max-min), bs)
  56. }
  57. // RandString 产生一个随机字符串,其长度为[min, max)。
  58. // bs 可用的随机字符串。
  59. func RandString(min, max int, bs []byte) string {
  60. return string(RandBytes(min, max, bs))
  61. }
  62. // Rands 提供了对参数的简单包装,方便用户批量产生相同的类型的随机字符串。
  63. type Rands struct {
  64. random *rand.Rand
  65. min, max int
  66. bytes []byte
  67. hasBuffer bool
  68. channel chan []byte
  69. done chan struct{}
  70. }
  71. // New 声明一个 Rands 变量。
  72. //
  73. // seed 随机种子,若为 0 表示使用当前时间作为随机种子。
  74. // bufferSize 缓存的随机字符串数量,若为 0,表示不缓存。
  75. func New(seed int64, bufferSize, min, max int, bs []byte) (*Rands, error) {
  76. checkArgs(min, max, bs)
  77. if seed == 0 {
  78. seed = time.Now().UnixNano()
  79. }
  80. ret := &Rands{
  81. random: rand.New(rand.NewSource(seed)),
  82. min: min,
  83. max: max,
  84. bytes: bs,
  85. hasBuffer: bufferSize > 0,
  86. done: make(chan struct{}),
  87. }
  88. if ret.hasBuffer {
  89. ret.channel = make(chan []byte, bufferSize)
  90. go func() {
  91. for {
  92. select {
  93. case <-ret.done:
  94. close(ret.channel)
  95. return
  96. case ret.channel <- genBytes(ret.random, min+ret.random.Intn(max-min), bs):
  97. }
  98. } // end ofr
  99. }()
  100. }
  101. return ret, nil
  102. }
  103. // Seed 重新指定随机种子。
  104. func (r *Rands) Seed(seed int64) {
  105. r.random.Seed(seed)
  106. }
  107. // Bytes 产生随机字符数组,功能与全局函数Bytes()相同,但参数通过New()预先指定。
  108. func (r *Rands) Bytes() []byte {
  109. if r.hasBuffer {
  110. if ret, ok := <-r.channel; ok {
  111. return ret
  112. }
  113. return nil
  114. }
  115. return genBytes(r.random, r.min+r.random.Intn(r.max-r.min), r.bytes)
  116. }
  117. // String 产生一个随机字符串,功能与全局函数 String() 相同,但参数通过 New() 预先指定。
  118. func (r *Rands) String() string {
  119. if r.hasBuffer {
  120. return string(<-r.channel)
  121. }
  122. return string(r.Bytes())
  123. }
  124. // Stop 停止产生随机字符串
  125. func (r *Rands) Stop() {
  126. r.done <- struct{}{}
  127. }
  128. // 生成指定指定长度的随机字符数组
  129. func genBytes(r *rand.Rand, l int, bs []byte) []byte {
  130. ret := make([]byte, l, l)
  131. for i := 0; i < l; i++ {
  132. index := r.Intn(len(bs))
  133. ret[i] = bs[index]
  134. }
  135. return ret
  136. }
  137. // 检测各个参数是否合法
  138. func checkArgs(min, max int, bs []byte) {
  139. if min <= 0 {
  140. panic("min 值必须大于 0")
  141. }
  142. if max <= min {
  143. panic("max 必须大于 min")
  144. }
  145. if len(bs) == 0 {
  146. panic("无效的 bs 参数")
  147. }
  148. }