脚本之家,脚本语言编程技术及教程分享平台!
分类导航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服务器之家 - 脚本之家 - Golang - go语言生成随机数和随机字符串的实现方法

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

2022-01-20 00:46kuteng Golang

随机数在很多时候都可以用到,尤其是登录时,本文就详细的介绍一下go语言生成随机数和随机字符串的实现方法,具有一定的参考价值,感兴趣的可以了解一下

生成随机数

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

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

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
package main
 
import (
    "fmt"
    "math/rand"
    "os"
    "strconv"
    "time"
)
 
func random(min, max int) int {
    return rand.Intn(max-min) + min
}

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

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

?
1
2
3
4
5
6
7
func main() {
    MIN := 0
    MAX := 100
    TOTAL := 100
    SEED := time.Now().Unix()
 
    arguments := os.Args

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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 代码:

?
1
2
3
4
5
6
7
8
    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 将会生成如下输出:

?
1
2
3
4
5
6
7
8
9
10
11
12
$ 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 代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
package main
 
import (
    "fmt"
    "math/rand"
    "os"
    "strconv"
    "time"
)
 
func random(min, max int) int {
    return rand.Intn(max-min) + min
}

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

?
1
2
3
4
5
6
7
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 的第三个代码段如下:

?
1
2
3
4
5
6
7
8
switch len(arguments) {
case 2:
    LENGTH, _ = strconv.ParseInt(os.Args[1], 10, 64)
default:
    fmt.Println("Using default values!")
}
 
   rand.Seed(SEED)

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
    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 并传入合适的命令行参数将生成如下输出:

?
1
2
3
4
5
6
7
8
9
10
$ 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语言生成随机数和随机字符串内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://www.topgoer.cn/blog-84.html

延伸 · 阅读

精彩推荐
  • Golanggo语言制作端口扫描器

    go语言制作端口扫描器

    本文给大家分享的是使用go语言编写的TCP端口扫描器,可以选择IP范围,扫描的端口,以及多线程,有需要的小伙伴可以参考下。 ...

    脚本之家3642020-04-25
  • Golanggolang 通过ssh代理连接mysql的操作

    golang 通过ssh代理连接mysql的操作

    这篇文章主要介绍了golang 通过ssh代理连接mysql的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    a165861639710342021-03-08
  • GolangGolang通脉之数据类型详情

    Golang通脉之数据类型详情

    这篇文章主要介绍了Golang通脉之数据类型,在编程语言中标识符就是定义的具有某种意义的词,比如变量名、常量名、函数名等等,Go语言中标识符允许由...

    4272021-11-24
  • Golanggolang如何使用struct的tag属性的详细介绍

    golang如何使用struct的tag属性的详细介绍

    这篇文章主要介绍了golang如何使用struct的tag属性的详细介绍,从例子说起,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看...

    Go语言中文网11352020-05-21
  • Golanggolang的httpserver优雅重启方法详解

    golang的httpserver优雅重启方法详解

    这篇文章主要给大家介绍了关于golang的httpserver优雅重启的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,...

    helight2992020-05-14
  • GolangGolang中Bit数组的实现方式

    Golang中Bit数组的实现方式

    这篇文章主要介绍了Golang中Bit数组的实现方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    天易独尊11682021-06-09
  • Golanggo日志系统logrus显示文件和行号的操作

    go日志系统logrus显示文件和行号的操作

    这篇文章主要介绍了go日志系统logrus显示文件和行号的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    SmallQinYan12302021-02-02
  • Golanggolang json.Marshal 特殊html字符被转义的解决方法

    golang json.Marshal 特殊html字符被转义的解决方法

    今天小编就为大家分享一篇golang json.Marshal 特殊html字符被转义的解决方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧 ...

    李浩的life12792020-05-27