以前發現了golang標準庫中又兩個rand軟件包,開始很是想知道他們之間的差別.golang
math/rand
軟件包能夠用於簡單的遊戲,但不能用於真正的隨機性。安全
math/rand
: 僞隨機數生成器crypto/rand
: 加密安全的隨機數生成器Rob Pike的代碼併發
package main import ( "fmt" "math/rand" "time" ) func main() { c := fanIn(boring("Joe"), boring("Ann")) for i := 0; i < 10; i++ { fmt.Println(<-c) } fmt.Println("You're both boring; I'm leaving.") } func boring(msg string) <-chan string { c := make(chan string) go func() { for i := 0; ; i++ { c <- fmt.Sprintf("%s %d", msg, i) time.Sleep(time.Duration(rand.Intn(1e3)) * time.Millisecond) } }() return c } // FAN IN func fanIn(input1, input2 <-chan string) <-chan string { c := make(chan string) go func() { for { c <- <-input1 } }() go func() { for { c <- <-input2 } }() return c }
實現僞隨機數生成器。函數
隨機數由源生成。頂級函數(例如Float64和Int)使用默認的共享源,該源在每次運行程序時都會產生肯定的值序列。 若是每次運行須要不一樣的行爲, 請使用種子函數初始化默認的源。 默認的Source可安全地供多個goroutine併發使用,但不是由NewSource建立的Source。加密
package main import ( "fmt" "math/rand" "time" ) func init(){ rand.Seed(time.Now().UTC().UnixNano()) } func main() { // launches 2 generators and the fanIn collector function c := fanIn(genrt(), genrt()) for i := 0; i < 10000; i++ { fmt.Println(<-c) } } func fanIn(a <-chan int, b <-chan int) <-chan string { c := make(chan string) // launch collector from a to channel go func() { var count int for { count += <-a c <- fmt.Sprintf("Tally of A is: %d", count) } }() // launch collector from b to channel go func() { var count int for { count += <-b c <- fmt.Sprintf("Tally of B is: %d", count) } }() return c } func genrt() <-chan int { c := make(chan int) // launch generator of Dice rolls go func() { for i := 0; ; i++ { c <- rand.Intn(6) + 1 time.Sleep(time.Duration(500 * time.Millisecond)) } }() return c }
打印輸出code
... Tally of B is: 17656 Tally of A is: 17438 Tally of A is: 17440 Tally of B is: 17659 Tally of B is: 17660 Tally of A is: 17445
實現了加密安全的隨機數生成器。遊戲
package main import ( "crypto/rand" "fmt" "math/big" "time" ) func main() { // launches 2 generatores and the fanIn collector function c := fanIn(genrt(), genrt()) for i := 0; i < 10000; i++ { fmt.Println(<-c) } } func fanIn(a <-chan int, b <-chan int) <-chan string { c := make(chan string) // launch collector from a to channel go func() { var count int for { count += <-a c <- fmt.Sprintf("Tally of A is: %d", count) } }() // launch collector from b to channel go func() { var count int for { count += <-b c <- fmt.Sprintf("Tally of B is: %d", count) } }() return c } func genrt() <-chan int { c := make(chan int) // launch generator of Dice rolls go func() { for i := 0; ; i++ { dice, err := rand.Int(rand.Reader, big.NewInt(6)) if err != nil { fmt.Println(err) } c <- int(dice.Int64()) + 1 time.Sleep(time.Duration(1 * time.Millisecond)) } }() return c }
打印輸出get
... Tally of B is: 17496 Tally of A is: 17570 Tally of A is: 17574 Tally of B is: 17500 Tally of B is: 17505 Tally of A is: 17576