用習慣了python裏面的random模塊,隨機數真的是順手就來,這次用到了go,沒想到生成的居然是僞隨機數,首次生成雖然隨機了,但是再次生成就一直是這個,這怎麼搞,完全沒隨機啊,下面說一說踩過的坑!!!
文章目錄
1. 首先來說一下什麼是隨機數
隨機數,是使用一個確定性的算法計算出來隨機數序。在程序開發中經常需要產生隨機數,如隨機數驗證碼登陸、作爲唯一身份標識數據等等。
2. go中生成隨機數的有兩個包,分別是“math/rand”和“crypto/rand”,
- 前者實現了僞隨機數生成器,
- 後者實現了用於加解密的跟安全的隨機數生成器,當然,性能也就降下來了,畢竟魚與熊掌不可兼得
3. 隨機數生成
func main() {
for i:=0; i<10; i++ {
fmt.Print(rand.Intn(10), " ")
}
}
結果: 1 7 7 9 1 8 5 0 6 0 --> 生成的是
再來一次: 1 7 7 9 1 8 5 0 6 0 -->還是這個結果,這叫啥子隨機數,查看文檔,繼續試驗
4. 初始化隨機種子函數(下面爲官方文檔說明)
func Seed(seed int64)
Seed uses the provided seed value to initialize the default Source to a deterministic state. If Seed is not called, the generator behaves as if seeded by Seed(1). Seed values that have the same remainder when divided by 2^31-1 generate the same pseudo-random sequence. Seed, unlike the Rand.Seed method, is safe for concurrent use.
我認爲的意思就是系統每次都會先用Seed函數初始化系統資源,如果用戶不提供seed參數,則默認用seed=1來初始化,這就是爲什麼每次都輸出一樣的值的原因,而且,Seed方法是併發安全的.
所謂種子,通俗理解可以理解爲一個抽獎的獎池,我們自定義一個獎池,從我們的獎池中進行隨機抽獎,種子就是我們獎池中的數據
5. 使用種子生成
func main() {
// 我們一般使用系統時間的不確定性來進行初始化
rand.Seed(time.Now().Unix())
for i:=0; i<10; i++ {
fmt.Print(rand.Intn(10), " ")
}
}
或者我們可以使用rand.NewSource()
func checkSumBuilder() (string, string, string){
r := rand.New(rand.NewSource(time.Now().UnixNano()))
num := r.Intn(128)
}
6. Intn函數
func Intn(n int) int
生成 [0,n)區間的一個隨機數(注意:不包括n)
更多詳情查看math/rand官網
7. 生成指定位數的隨機數(以生成8位爲例)
package main
import (
"fmt"
"math/rand"
)
func main() {
s := fmt.Sprintf("%08v", rand.New(rand.NewSource(time.Now().UnixNano())).Int63n(100000000))
fmt.Println(s)
}
8. 真隨機數
如果我們的應用對安全性要求比較高,需要使用真隨機數的話,那麼可以使用 crypto/rand 包中的方法,這樣生成的每次都是不同的隨機數.
package main
import (
"crypto/rand"
"fmt"
"math/big"
)
func main() {
// 生成 10 個 [0, 128) 範圍的真隨機數。
for i := 0; i < 10; i++ {
result, _ := rand.Int(rand.Reader, big.NewInt(128))
fmt.Println(result)
}
}