伪随机数
import (
"math/rand"
"fmt"
)
func main(){
rand.Seed(1)
fmt.Println(rand.Intn(20))
fmt.Println(rand.Intn(20))
fmt.Println(rand.Intn(20))
}
将该程序运行多次,每次打印的随机数都是:1,7,7, 该随机数与seed有关
真随机数
import (
"math/big"
"crypto/rand"
"fmt"
)
func main(){
a, _ := rand.Int(rand.Reader, big.NewInt(255))
b, _ := rand.Int(rand.Reader, big.NewInt(255))
c, _ := rand.Int(rand.Reader, big.NewInt(255))
d, _ := rand.Int(rand.Reader, big.NewInt(255))
fmt.Println(a)
fmt.Println(b)
fmt.Println(c)
fmt.Println(d)
}
这个是真正的随机数,每次都是随机
伪随机数导致的问题
场景:开了一个http服务,随机生成ip地址,代码如下
import (
"encoding/json"
"net/http"
"math/rand"
"time"
"fmt"
)
func main(){
http.HandleFunc("/job", func(writer http.ResponseWriter, request *http.Request) {
rand.Seed(time.Now().Unix())
ip := fmt.Sprintf("%d.%d.%d.%d", rand.Intn(255), rand.Intn(255), rand.Intn(255), rand.Intn(255))
result := make(map[string]string)
result["data"] = ip
b,_ := json.Marshal(result)
writer.Write(b)
})
err := http.ListenAndServe(":28888", nil)
if err !=nil {
panic(err)
}
}
客户端开启多线程,请求服务端的随机ip地址,代码:
import (
"net/http"
"io/ioutil"
"fmt"
"time"
)
func main() {
pool := make(chan struct{}, 5)
for ; ; {
pool <- struct{}{}
go func(c chan struct{}) {
defer func() {
<- c
}()
resp,err := http.Get("http://127.0.0.1:28888/job")
if err != nil {
fmt.Println(err)
}
if resp != nil {
if resp.Body != nil {
defer func() {
resp.Body.Close()
}()
}
}
body,err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println(err)
}
fmt.Println(string(body))
time.Sleep(time.Second)
}(pool)
}
select {}
}
打印之后发现,每次5个协程请求的ip地址是一模一样的
原因:多协程同时请求http服务,获取ip地址的时候,rand.Seed(time.Now().Unix())设置的随机数种子一样,生成的随机数也是一样的,最后ip就重复了
解决办法:把伪随机数换成真随机数