go语言生成随机数和随机字符串的实现方法

 更新时间:2021年12月08日 15:12:53   作者:kuteng  
随机数在很多时候都可以用到,尤其是登录时,本文就详细的介绍一下go语言生成随机数和随机字符串的实现方法,具有一定的参考价值,感兴趣的可以了解一下

生成随机数

随机数的生成是计算机科学的一个研究领域,同时也是一种艺术。这是因为计算机是纯粹的逻辑机器,所以使用计算机生成随机数异常困难!

你可以用 math/rand 包来生成随机数。开始生成随机数之前首先需要一个种子,种子用于整个过程的初始化,它相当重要。因为如果你每次都用同样的种子初始化,那么就总是会得到相同的随机数序列。这意味着每个人都可以重新生成同一个序列,那这个序列就根本不能再算是随机的了!

我们将用来生成随机数的程序名为 randomNumbers.go,下面分成四个部分进行介绍。这个程序需要几个参数,分别是生成随机数的下限、生成随机数的上限、生成随机数的数量。如果你还用了第四个命令参数,那么程序会将它作为随机数生成器的种子。在测试的时候,你就可以再次使用这个参数生成相同的数列。

程序的第一部分如下所示:

package main

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

func random(min, max int) int {
    return rand.Intn(max-min) + min
}

random() 函数完成了所有的工作,它通过根据指定的范围调用 rand.Intn() 生成随机数。

这个命令行程序的第二部分如下:

func main() {
    MIN := 0
    MAX := 100
    TOTAL := 100
    SEED := time.Now().Unix()

    arguments := os.Args

这一部分对程序中将会用到的变量进行了初始化。

randomNumbers.go 的第三部分包含如下的 Go 代码:

    switch len(arguments) {
    case 2:
        fmt.Println("Usage: ./randomNumbers MIN MAX TOTAL SEED")
        MIN, _ = strconv.Atoi(arguments[1])
        MAX = MIN + 100
    case 3:
        fmt.Println("Usage: ./randomNumbers MIN MAX TOTAL SEED")
        MIN, _ = strconv.Atoi(arguments[1])
        MAX, _ = strconv.Atoi(arguments[2])
    case 4:
        fmt.Println("Usage: ./randomNumbers MIN MAX TOTAL SEED")
        MIN, _ = strconv.Atoi(arguments[1])
        MAX, _ = strconv.Atoi(arguments[2])
        TOTAL, _ = strconv.Atoi(arguments[3])
    case 5:
        MIN, _ = strconv.Atoi(arguments[1])
        MAX, _ = strconv.Atoi(arguments[2])
        TOTAL, _ = strconv.Atoi(arguments[3])
        SEED, _ = strconv.ParseInt(arguments[4], 10, 64)
    default:
        fmt.Println("Using default values!")
    }

switch 代码块背后的逻辑相对简单:根据命令行参数的数量决定程序中的参数是使用缺省的默认值还是使用用户提供的值。为了简化程序,strconv.Atoi() 和 strconv.ParseInt() 函数返回的 error 参数使用下划线字符接收,然后被忽略。如果是商业程序就千万不能忽略 strconv.Atoi() 和 strconv.ParseInt() 函数返回的 error 参数!

最后,使用 strconv.ParseInt() 对 SEED 变量赋新的值是因为 rand.Seed() 函数要求的参数类型是 int64。strconv.ParseInt() 的第一个参数是要解析的字符串,第二个参数是输出数的基数,第三个参数是输出数的位数。由于我们想要生成的是一个 64 位的十进制整数,所以使用 10 作为基数,使用 64 作为位数。注意,如果你想解析无符号的整数的话应该使用 strconv.ParseUint() 函数代替。

randomNumbers.go 的最后一部分是如下的 Go 代码:

    rand.Seed(SEED)
    for i := 0; i < TOTAL; i++ {
        myrand := random(MIN, MAX)
        fmt.Print(myrand)
        fmt.Print(" ")
    }
    fmt.Println()
}

除了使用 Unix 时间戳作为随机数生成器的种子,你还可以使用 /dev/random 这个系统设备。你可以在第 8 章“Go Unix系统编程”中了解 /dev/random 的相关内容。

执行 randomNumbers.go 将会生成如下输出:

$ go run randomNumbers.go
75 69 15 75 62 67 64 8 73 1 83 92 7 34 8 70 22 58 38 8 54 91 65 1 50 76 5 82 61 90 10 38 40 63 6 28 51 54 49 27 52 92 76 35 44 9 66 76 90 10 29 22 20 83 33 92 80 50 62 26 19 45 56 75 40 30 97 23 87 10 43 11 42 65 80 82 25 53 27 51 99 88 53 36 37 73 52 61 4 81 71 57 30 72 51 55 62 63 79
$ go run randomNumbers.go 1 3 2
Usage: ./randomNumbers MIN MAX TOTAL SEED
1 1 
$ go run randomNumbers.go 1 3 2
Usage: ./randomNumbers MIN MAX TOTAL SEED
2 2
$ go run randomNumbers.go 1 5 10 10
3 1 4 4 1 1 4 4 4 3
$ go run randomNumbers.go 1 5 10 10
3 1 4 4 1 1 4 4 4 3

如果你对随机数生成真的很有兴趣,那么你应该先读一下 Donald E.Knuth 写的 The Art of Computer Programming (Addison-Wesley Professional, 2011) 的第二卷。

如果需要用 Go 生成更安全的随机数的话,你可以使用 crypto/rand 包。这个包中实现了满足密码学安全的伪随机数生成器。你可以在 https://golang.org/pkg/crypto/rand/ 文档页面了解更多关于 crypto/rand 包的信息。

生成随机字符串

一旦你知道了计算机是如何呈现出单个字符,从随机数过渡到随机字符串就不难了。这一节将会介绍如何使用前一节中 randomNumbers.go 的代码生成难以猜出的密码。用于完成这个任务的 Go 程序叫做 generatePassword.go,下面将分四个部分进行介绍。这个程序只需要一个命令行参数,就是你需要生成的密码的长度。

generatePassword.go 的第一部分包含如下的 Go 代码:

package main

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

func random(min, max int) int {
    return rand.Intn(max-min) + min
}

generatePassword.go 的第二个代码段如下:

func main() {
    MIN := 0
    MAX := 94
    SEED := time.Now().Unix()
    var LENGTH int64 = 8

    arguments := os.Arg

我们只想得到可打印的 ASCII 字符,所以对生成随机数的范围进行了限制。ASCII 字符表中可打印的字符一共有 94 个。这意味着该程序生成的随机数的范围应该是从 0 到 94 且不包括 94。

generatePassword.go 的第三个代码段如下:

    switch len(arguments) {
    case 2:
        LENGTH, _ = strconv.ParseInt(os.Args[1], 10, 64)
    default:
        fmt.Println("Using default values!")
    }

       rand.Seed(SEED)

generatePassword.go 的最后一部分如下:

    startChar := "!"
    var i int64 = 1
    for {
        myRand := random(MIN, MAX)
        newChar := string(startChar[0] + byte(myRand))
        fmt.Print(newChar)
        if i == LENGTH {
            break
        }
        i++
    }
    fmt.Println()
}

startChar 参数保存了这个程序可以生成的第一个 ASCII 字符,也就是十进制 ASCII 值为 33 的感叹号。已知该程序生成的随机数小于 94,可以计算出生成的最大的 ASCII 值为 93 + 33,等于 126,也就是 ~ 的 ASCII 值。下面的输出是含有十进制数值的 ASCII 字符表:

The decimal set:

  0 nul    1 soh    2 stx    3 etx    4 eot    5 enq    6 ack    7 bel
  8 bs     9 ht    10 nl    11 vt    12 np    13 cr    14 so    15 si
 16 dle   17 dc1   18 dc2   19 dc3   20 dc4   21 nak   22 syn   23 etb
 24 can   25 em    26 sub   27 esc   28 fs    29 gs    30 rs    31 us
 32 sp    33  !    34  "    35  #    36  $    37  %    38  &    39  '
 40  (    41  )    42  *    43  +    44  ,    45  -    46  .    47  /
 48  0    49  1    50  2    51  3    52  4    53  5    54  6    55  7
 56  8    57  9    58  :    59  ;    60  <    61  =    62  >    63  ?
 64  @    65  A    66  B    67  C    68  D    69  E    70  F    71  G
 72  H    73  I    74  J    75  K    76  L    77  M    78  N    79  O
 80  P    81  Q    82  R    83  S    84  T    85  U    86  V    87  W
 88  X    89  Y    90  Z    91  [    92  \    93  ]    94  ^    95  _
 96  `    97  a    98  b    99  c   100  d   101  e   102  f   103  g
104  h   105  i   106  j   107  k   108  l   109  m   110  n   111  o
112  p   113  q   114  r   115  s   116  t   117  u   118  v   119  w
120  x   121  y   122  z   123  {   124  |   125  }   126  ~   127 del

在你最喜欢的 Unix shell 中输入 man ascii 就能生成易读的 ASCII 字符表。

执行 generatePassword.go 并传入合适的命令行参数将生成如下输出:

$ go run generatePassword.go
Using default values!
ugs$5mv1
$ go run generatePassword.go
Using default values!
PA/8hA@?
$ go run generatePassword.go 20
HBR+=3\UA'B@ExT4QG|o
$ go run generatePassword.go 20
XLcr|R{*pX/::'t2u^T'

到此这篇关于go语言生成随机数和随机字符串的实现方法的文章就介绍到这了,更多相关go语言生成随机数和随机字符串内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Golang中常用的语法糖分享

    Golang中常用的语法糖分享

    语法糖,也称糖语法,是由英国计算机科学家彼得·兰丁提出的,用于表示编程语言中的某种类型的语法,这些语法不会影响功能,但使用起来却很方便,本文就来看看Golang中常用的语法糖有哪些吧
    2023-05-05
  • Golang限流器time/rate设计与实现详解

    Golang限流器time/rate设计与实现详解

    在 Golang 库中官方给我们提供了限流器的实现golang.org/x/time/rate,它是基于令牌桶算法(Token Bucket)设计实现的,下面我们就来看看他的具体使用吧
    2024-03-03
  • 详解go-zero如何实现计数器限流

    详解go-zero如何实现计数器限流

    这篇文章主要来和大家说说限流,主要包括计数器限流算法以及具体的代码实现,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-08-08
  • golang fmt占位符的使用详解

    golang fmt占位符的使用详解

    这篇文章主要介绍了golang fmt占位符的使用详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • GoLang协程库libtask学习笔记

    GoLang协程库libtask学习笔记

    libtask一个C语言的协程库,是go语言的前身很早期的原型. 测试机器是我的mac air 安装的centos虚拟机(只有一个核), 代码没有采用任何优化,只是使用默认配置
    2022-12-12
  • 如何使用Go语言获取当天、昨天、明天、某天0点时间戳以及格式化时间

    如何使用Go语言获取当天、昨天、明天、某天0点时间戳以及格式化时间

    这篇文章主要给大家介绍了关于如何使用Go语言获取当天、昨天、明天、某天0点时间戳以及格式化时间的相关资料,格式化时间戳是将时间戳转换为特定的日期和时间格式,文中通过代码示例介绍的非常详细,需要的朋友可以参考下
    2023-10-10
  • golang如何去除多余空白字符(含制表符)

    golang如何去除多余空白字符(含制表符)

    这篇文章主要介绍了golang去除多余空白字符(含制表符)的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04
  • Golang标准库和外部库的性能比较

    Golang标准库和外部库的性能比较

    这篇文章主要介绍Golang标准库和外部库的性能比较,下面文章讲围绕这两点展开内容,感兴趣的小伙伴可以参考一下
    2021-10-10
  • Go语言设计模式之结构型模式

    Go语言设计模式之结构型模式

    本文主要聚焦在结构型模式(Structural Pattern)上,其主要思想是将多个对象组装成较大的结构,并同时保持结构的灵活和高效,从程序的结构上解决模块之间的耦合问题
    2021-06-06
  • Go语言中定时任务库Cron使用方法介绍

    Go语言中定时任务库Cron使用方法介绍

    cron的意思计划任务,说白了就是定时任务。我和系统约个时间,你在几点几分几秒或者每隔几分钟跑一个任务(job),今天通过本文给大家介绍下Go语言中定时任务库Cron使用方法,感兴趣的朋友一起看看吧
    2022-03-03

最新评论