golang中随机数rand的使用

目录
  • 1、math/rand
  • 2、crypto/rand

1、math/rand

随机数从资源生成。包水平的函数都使用的默认的公共资源。

该资源会在程序每次运行时都产生确定的序列。如果需要每次运行产生不同的序列,应使用Seed函数进行初始化。默认资源可以安全的用于多go程并发。

关于种子seed
程序启动的时候,种子的初始值是一样的,也就是说随机数是一样的,什么意思呢?

package main

import (
   "fmt"
   "math/rand"
)

func main(){
   data := rand.Int63n(100)
   fmt.Println(data)
}
 

每次运行go run main.go
打印的都是 10

如果我们播放种子

package main

import (
   "fmt"
   "math/rand"
   "time"
)

func main(){
   rand.Seed(time.Now().Unix()) // unix 时间戳,秒
   data := rand.Int63n(100)
   fmt.Println(data)
}

这样每次执行go run main.go

打印的结果就不一样,但是,根据随机数的特性,如果两次执行的时间戳是在同一秒,那么打印的结果是相同的。
以上的随机数相同的情况是发生在程序启动的时候,如果程序启动后,每次生成随机数会怎样呢?

package main

import (
   "fmt"
   "math/rand"
)

func main(){
   for i := 0; i<5; i++ {
      data := rand.Int63n(100)
      fmt.Println(data)
   }
}

运行 go run main.go
打印
10
51
21
51
37

再次运行 go run main.go
打印
10
51
21
51
37

可见每次启动的结果是一样的;但是程序启动后,每次的随机数都不尽相同,是随机的。

如果再加上种子呢?

package main

import (
   "fmt"
   "math/rand"
   "time"
)

func main(){
   for i := 0; i<5; i++ {
      rand.Seed(time.Now().Unix()) // unix 时间戳,秒
      data := rand.Int63n(100)
      fmt.Println(data)
   }
}

运行 go run main.go
打印
86
86
86
86
86

再次运行 go run main.go
打印
72
72
72
72
72

每次启动程序,因为种子不一样,所以随机数不一样;但是程序启动后,每次也都是播放种子,秒级时间戳,如果时间戳一样,就导致种子一样,生成的随机数就一样,所以五次的随机数是一样的。

通过上面的例子。可以知道,播放种子不是必须的,除非要求每次启动程序的时候随机数不一样。

并且,要设置种子的情况下,应该放在整个程序启动的时候,而且只需要设置一次即可。修改上面的例子:

package main

import (
   "fmt"
   "math/rand"
   "time"
)

func main(){
   rand.Seed(time.Now().UnixNano()) // 纳秒时间戳
   for i := 0; i<5; i++ {
      data := rand.Int63n(100)
      fmt.Println(data)
   }
}

运行 go run main.go
打印
3
49
46
83
25

再次运行 go run main.go
打印
39
3
14
42
65

这次就是理想的结果了。使用纳秒时间戳基本就没问题了,因为我们的程序几乎不会在1纳秒时间内多次启动的。

下面来讲讲rand包的具体用法

rand 包提供了两块的内容,一块是基于 Rand 结构体及其方法;另一块是基于 Rand 结构体再封装的可直接调用的方法 rand.xxx,查看源码就知道它们是同样的功能。

所以,生成随机数有两种方式

rander := rand.New(rand.NewSource(time.Now().UnixNano()))
n1 := rander.Intn(100)

rand.Seed(time.Now().UnixNano())
n2 := rand.Intn(100)

使用第一种方法,将 rander 作为包的全局变量,这样就只会设置一次种子。

var Rander = rand.New(rand.NewSource(time.Now().UnixNano()))

随机整数

func (r *Rand) Int() int
func (r *Rand) Int31() int32
func (r *Rand) Int63() int64
func (r *Rand) Uint32() uint32
func (r *Rand) Uint64() uint64
func (r *Rand) Intn(n int) int
func (r *Rand) Int31n(n int32) int32
func (r *Rand) Int63n(n int64) int64

Int, Int31, Int63 生成的数都太大,一般使用 Intn, Int31n, Int63n。得到的范围 [0, n),想要得到 [0, n],就要使用 Intn(n + 1),想要得到 [10, 100] 的随机数,就要使用 Intn(91) + 10。

随机浮点数

func (r *Rand) Float32() float32
func (r *Rand) Float64() float64

得到 [0, 1) 之间的浮点数,32单精度,64双精度。

基于正态分布的随机浮点数

func (r *Rand) NormFloat64() float64

基于指数分布的随机浮点数

func (r *Rand) ExpFloat64() float64

随机序列

func (r *Rand) Perm(n int) []int

返回一个有n个元素的,[0,n)范围内整数的伪随机排列的切片。

Rander.Perm(10) // [1 8 0 4 7 6 3 2 9 5]

总结:

package main

import (
    "fmt"
    "math/rand"
    "strings"
    "time"
)

func main() {
    s := RandString(10)
    fmt.Println(s)
}

var Rander = rand.New(rand.NewSource(time.Now().UnixNano()))

const letterString = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
const numLetterString = "0123456789"

// 随机生成字符串
func RandStr(n int, letter string) string {
    str := []byte(letter)
    res := ""
    for i := 0; i < n; i++ {
        res += fmt.Sprintf("%c", str[Rander.Intn(strings.Count(letter, "") - 1)])
    }
    return res
}

func RandNumStr(n int) string {
    return RandStr(n, numLetterString)
}

func RandString(n int) string {
    return RandStr(n, letterString)
}

func RandOrder(n int) string {
    return time.Now().Format("20060102150405") + RandNumStr(n)
}

// 包含min, max
func RandNum(min , max int) int {
    return Rander.Intn(max - min + 1) + min
}

2、crypto/rand

实现了用于加解密的更安全的随机数生成器。

变量 var Reader io.Reader
是一个全局、共享的密码用强随机生成器。在Unix类型系统中,会从/dev/urandom读取;而windows中会调用RtlGenRandom API。

提供的方法

1、返回一个基于[0, max)的随机数

// Int returns a uniform random value in [0, max). It panics if max <= 0.
func Int(rand io.Reader, max *big.Int) (n *big.Int, err error)

示例

r, err := rand.Int(rand.Reader, big.NewInt(100))
fmt.Println(r.Int64(), err)

2、根据指定的位数bits,返回一个数,大概率是素数,(不知道这个函数是干嘛用的)

// Prime returns a number, p, of the given size, such that p is prime
// with high probability.
// Prime will return error for any error returned by rand.Read or if bits < 2.
func Prime(rand io.Reader, bits int) (p *big.Int, err error)

示例

p, err := rand.Prime(rand.Reader, 8)
fmt.Println(p.Int64(), err)

8个二进制位的最大值为255,此处会随机返回小于255的素数。

3、生成随机的二进制序列

// Read is a helper function that calls Reader.Read using io.ReadFull.
// On return, n == len(b) if and only if err == nil.
func Read(b []byte) (n int, err error) {
    return io.ReadFull(Reader, b)
}

比如,随机生成16个字节的数据

var b [16]byte
n, err := rand.Read(b[:])
fmt.Println(n, err)
fmt.Println(b)

返回值
16 <nil>
[94 184 113 36 224 18 239 52 69 242 14 84 174 113 125 15]

我们可以将其转换成16进制数,也就是32位

buf := make([]byte, 32)
hex.Encode(buf, b[:])
fmt.Println(string(buf))

得到
5eb87124e012ef3445f20e54ae717d0f

通过这个方法可以生成随机的字符串。

到此这篇关于golang中随机数rand的使用的文章就介绍到这了,更多相关golang随机数rand内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • golang生成指定位数的随机数的方法

    1.随机数 随机数,是使用一个确定性的算法计算出来随机数序.在程序开发中经常需要产生随机数,如随机数验证码登陆.作为唯一身份标识数据等等. 2.rand库 golang中产生随机数主要有两个包,分别是"math/rand"和"crypto/rand". "math/rand"的rand包实现了伪随机数生成器. "crypto/rand"的rand包实现了用于加解密的更安全的随机数生成器. 3.生成指定位数随机数 以生成六位随机

  • golang 随机数的两种方式

    golang支持两种随机数生成方式: math/rand          // 伪随机 crypto/rand        // 真随机 math/rand伪随机生成的数字是确定的,不论在什么机器.什么时间,只要执行的随机代码一样,那么生成的随机数就一样.为了尽量随机性,那么我们可以每次使用不同的seed来启动程序,就可以保证每次启动都产生新的随机数,聪明的你肯定想到了使用时间戳 func main() { fmt.Println(rand.Intn(100)) //设置随机数种子,由于种子

  • GoLang 中的随机数的示例代码

    随机数我们都知道,就是计算机通过某种算法,"随机"的生成一个数字.很多编程语言都有内置的方法来生成随机数,那么 GoLang 中是怎样一种情况呢? 伪随机数 我们都知道"随机数"在现实生活中的概念,可能你随手抛一个硬币,就可以说其结果是随机的,但是在计算机中要确定一个"随机数"真的是"随机数",那可是有标准的,不是你随随便便说是就是. 根据密码学原理,要想对一个"随机数"进行随机性检验有以下几个标准: 统计

  • Golang编程实现生成n个从a到b不重复随机数的方法

    本文实例讲述了Golang编程实现生成n个从a到b不重复随机数的方法.分享给大家供大家参考,具体如下: 代码很简单: 复制代码 代码如下: package test import (     "fmt"     "math/rand"     "time" ) //生成若干个不重复的随机数 func RandomTestBase() {     //测试5次     for i := 0; i < 5; i++ {         nums

  • 利用Golang生成整数随机数方法示例

    php随机数 生成一个给定范围的随机数,用 PHP 就太简单不过了,而且可以指定从负数到正整数的范围,如: <?php echo mt_rand(-988, 888); 这样就随机生成 -988 到 888 的随机数. 使用 Go 就要稍微麻烦一点.以下两个函数分别是生成一个最大范围内随机整数,和生成一个区间范围的随机整数: 生成一个最大范围内随机数 一定要给一个时间戳的种子,否则每次生成都是一样的值.这里就是生成 [0,100) 的随机数. func GenerateRandnum() int

  • golang中随机数rand的使用

    目录 1.math/rand 2.crypto/rand 1.math/rand 随机数从资源生成.包水平的函数都使用的默认的公共资源. 该资源会在程序每次运行时都产生确定的序列.如果需要每次运行产生不同的序列,应使用Seed函数进行初始化.默认资源可以安全的用于多go程并发. 关于种子seed程序启动的时候,种子的初始值是一样的,也就是说随机数是一样的,什么意思呢? package main import (    "fmt"    "math/rand" ) f

  • C语言中随机数rand()函数详解

      在生活中很多场景下都需要产生随机数,比如抽奖,打牌,游戏等场景下就需要使用随机数.在C语言标准库函数里面有专门用来产生随机数的函数rand,它的函数原型如下: int __cdecl rand(void);   rand函数没有参数,它的返回值就是随机数.下面通过一个简单的例子来测试一下rand函数. #include <stdio.h> #include <stdlib.h> int main(int argc, char** argv) { int i; i = rand(

  • 在Golang中使用http.FileServer返回静态文件的操作

    Golang中使用http.FileServer 使用http.FileServer可以管理向浏览器返回静态文件 http.Handle("/",http.FileServer(http.Dir("/Users/administrator/Desktop/public"))) err := http.ListenAndServe("0.0.0.0:8080",nil) if err!=nil{ fmt.Print(err); } 补充:golan

  • Golang中常见加密算法的总结

    目录 1.md5 加密——不可逆 2.hmacsha 加密——不可逆 hmac-md5加密 hamacsha1 加密 hamacsha 256 加密 hmacsha512加密 hamasha 调用 3.Sha 加密——不可逆 sha1 sha256 sha512 sha调用 4.base 加密 解密 加密 解密 base64 调用 5.AES 加密 CBC方式 ECB方式 CFB 方式 6.RSA加密 RSA加密 RSA分段加密 7.DES加密 内置库完成 使用第三方库 8.3DES加密算法 如

  • 有关C++中随机函数rand() 和srand() 的用法详解

    一.rand() 函数名:   rand 功   能:   随机数发生器 用   法:   int rand(void); 所在头文件: stdlib.h 函数说明 : rand()的内部实现是用线性同余法做的,它不是真的随机数,因其周期特别长,故在一定 的范围里可看成是随机的. rand()返回一随机数值的范围在0至RAND_MAX 间.RAND_MAX的范围最少是在32767之间(int).用 unsigned int 双字节是65535,四字节是4294967295的整数范围.0~RAND

  • SQL Server中的RAND函数的介绍和区间随机数值函数的实现

    工作中会遇到SQL Server模拟数据生成以及数值列值(如整型.日期和时间数据类型)随机填充等等任务,这些任务中都要使用到随机数.鉴于此,本文将对SQL Server中随机数的使用简单做个总结 . T-SQL 随机有关的三个函数 RAND([seed] 此函数生成从0到1之间随机 float 值(详细说明查看https://technet.microsoft.com/zh-cn/library/ms177610(v=sql.90).aspx). CHECKSUM ( * | expressio

  • Java中随机数的产生方式与原理详解

    Java中随机数的产生方式与原理 查阅随机数相关资料,特做整理 首先说一下java中产生随机数的几种方式 在j2se中我们可以使用Math.random()方法来产生一个随机数,这个产生的随机数是0-1之间的一个double,我们可以把他乘以100,他就是个100以内的随机数字,这个在j2me中没有. 在java.util这个包里面提供了一个Random的类,我们可以新建一个Random的对象来产生随机数,他可以生产随机整数.随机float.随机double.随机long,这个也是我们在j2me

  • 示例剖析golang中的CSP并发模型

    目录 1. 相关概念: 2. CSP (通信顺序进程) 3. channel:同步&传递消息 4. goroutine:实际并发执行的实体 5. golang调度器 1. 相关概念: 用户态:当一个进程在执行用户自己的代码时处于用户运行态(用户态) 内核态:当一个进程因为系统调用陷入内核代码中执行时处于内核运行态(内核态),引入内核态防止用户态的程序随意的操作内核地址空间,具有一定的安全保护作用.这种保护模式是通过内存页表操作等机制,保证进程间的地址空间不会相互冲突,一个进程的操作不会修改另一个

  • Golang 中反射的应用实例详解

    目录 引言 Golang类型设计原则 Golang 中为什么要使用反射/什么场景可以(应该)使用反射 举例场景: 反射的基本用法 反射的性能分析与优缺点 测试反射结构体初始化 测试结构体字段读取/赋值 测试结构体方法调用 优缺点 反射在 okr 中的简单应用 结论 引言 首先来一段简单的代码逻辑热身,下面的代码大家觉得应该会打印什么呢? type OKR struct { id int content string } func getOkrDetail(ctx context.Context,

随机推荐