github.com/zhongdalu/gf@v1.0.0/g/util/grand/grand_intn.go (about) 1 // Copyright 2018 gf Author(https://github.com/zhongdalu/gf). 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/zhongdalu/gf. 6 7 package grand 8 9 import ( 10 "crypto/rand" 11 "encoding/binary" 12 "os" 13 ) 14 15 const ( 16 // Buffer size for uint32 random number. 17 gBUFFER_SIZE = 10000 18 ) 19 20 var ( 21 // Buffer chan. 22 bufferChan = make(chan uint32, gBUFFER_SIZE) 23 ) 24 25 // It uses a asychronous goroutine to produce the random number, 26 // and a buffer chan to store the random number. So it has high performance 27 // to generate random number. 28 func init() { 29 step := 0 30 buffer := make([]byte, 1024) 31 go func() { 32 for { 33 if n, err := rand.Read(buffer); err != nil { 34 panic(err) 35 os.Exit(1) 36 } else { 37 // 使用缓冲区数据进行一次完整的随机数生成 38 for i := 0; i < n-4; { 39 bufferChan <- binary.LittleEndian.Uint32(buffer[i : i+4]) 40 i++ 41 } 42 // 充分利用缓冲区数据,随机索引递增 43 for i := 0; i < n; i++ { 44 step = int(buffer[0]) % 10 45 if step != 0 { 46 break 47 } 48 } 49 if step == 0 { 50 step = 2 51 } 52 for i := 0; i < n-4; { 53 bufferChan <- binary.BigEndian.Uint32(buffer[i : i+4]) 54 i += step 55 } 56 } 57 } 58 }() 59 } 60 61 // Intn returns a int number which is between 0 and max - [0, max). 62 // 63 // Note: 64 // 1. The result is greater than or equal to 0, but less than <max>; 65 // 2. The result number is 32bit and less than math.MaxUint32. 66 func Intn(max int) int { 67 n := int(<-bufferChan) % max 68 if (max > 0 && n < 0) || (max < 0 && n > 0) { 69 return -n 70 } 71 return n 72 }