Golang: math/rand 和 crypto/rand 區別

1. 前言

原文地址

以前發現了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
}

2. Math/rand 僞隨機數生成器

實現僞隨機數生成器。函數

隨機數由源生成。頂級函數(例如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

3. Crypto/rand 加密安全的隨機數生成器

實現了加密安全的隨機數生成器。遊戲

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
相關文章
相關標籤/搜索