go語言生成隨機數(shù)和隨機字符串的實現(xiàn)方法
生成隨機數(shù)
隨機數(shù)的生成是計算機科學的一個研究領域,同時也是一種藝術。這是因為計算機是純粹的邏輯機器,所以使用計算機生成隨機數(shù)異常困難!
你可以用 math/rand 包來生成隨機數(shù)。開始生成隨機數(shù)之前首先需要一個種子,種子用于整個過程的初始化,它相當重要。因為如果你每次都用同樣的種子初始化,那么就總是會得到相同的隨機數(shù)序列。這意味著每個人都可以重新生成同一個序列,那這個序列就根本不能再算是隨機的了!
我們將用來生成隨機數(shù)的程序名為 randomNumbers.go,下面分成四個部分進行介紹。這個程序需要幾個參數(shù),分別是生成隨機數(shù)的下限、生成隨機數(shù)的上限、生成隨機數(shù)的數(shù)量。如果你還用了第四個命令參數(shù),那么程序會將它作為隨機數(shù)生成器的種子。在測試的時候,你就可以再次使用這個參數(shù)生成相同的數(shù)列。
程序的第一部分如下所示:
package main import ( "fmt" "math/rand" "os" "strconv" "time" ) func random(min, max int) int { return rand.Intn(max-min) + min }
random() 函數(shù)完成了所有的工作,它通過根據(jù)指定的范圍調用 rand.Intn() 生成隨機數(shù)。
這個命令行程序的第二部分如下:
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 代碼塊背后的邏輯相對簡單:根據(jù)命令行參數(shù)的數(shù)量決定程序中的參數(shù)是使用缺省的默認值還是使用用戶提供的值。為了簡化程序,strconv.Atoi() 和 strconv.ParseInt() 函數(shù)返回的 error 參數(shù)使用下劃線字符接收,然后被忽略。如果是商業(yè)程序就千萬不能忽略 strconv.Atoi() 和 strconv.ParseInt() 函數(shù)返回的 error 參數(shù)!
最后,使用 strconv.ParseInt() 對 SEED 變量賦新的值是因為 rand.Seed() 函數(shù)要求的參數(shù)類型是 int64。strconv.ParseInt() 的第一個參數(shù)是要解析的字符串,第二個參數(shù)是輸出數(shù)的基數(shù),第三個參數(shù)是輸出數(shù)的位數(shù)。由于我們想要生成的是一個 64 位的十進制整數(shù),所以使用 10 作為基數(shù),使用 64 作為位數(shù)。注意,如果你想解析無符號的整數(shù)的話應該使用 strconv.ParseUint() 函數(shù)代替。
randomNumbers.go 的最后一部分是如下的 Go 代碼:
rand.Seed(SEED) for i := 0; i < TOTAL; i++ { myrand := random(MIN, MAX) fmt.Print(myrand) fmt.Print(" ") } fmt.Println() }
除了使用 Unix 時間戳作為隨機數(shù)生成器的種子,你還可以使用 /dev/random 這個系統(tǒng)設備。你可以在第 8 章“Go Unix系統(tǒng)編程”中了解 /dev/random 的相關內容。
執(zhí)行 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
如果你對隨機數(shù)生成真的很有興趣,那么你應該先讀一下 Donald E.Knuth 寫的 The Art of Computer Programming (Addison-Wesley Professional, 2011) 的第二卷。
如果需要用 Go 生成更安全的隨機數(shù)的話,你可以使用 crypto/rand 包。這個包中實現(xiàn)了滿足密碼學安全的偽隨機數(shù)生成器。你可以在 https://golang.org/pkg/crypto/rand/ 文檔頁面了解更多關于 crypto/rand 包的信息。
生成隨機字符串
一旦你知道了計算機是如何呈現(xiàn)出單個字符,從隨機數(shù)過渡到隨機字符串就不難了。這一節(jié)將會介紹如何使用前一節(jié)中 randomNumbers.go 的代碼生成難以猜出的密碼。用于完成這個任務的 Go 程序叫做 generatePassword.go,下面將分四個部分進行介紹。這個程序只需要一個命令行參數(shù),就是你需要生成的密碼的長度。
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 字符,所以對生成隨機數(shù)的范圍進行了限制。ASCII 字符表中可打印的字符一共有 94 個。這意味著該程序生成的隨機數(shù)的范圍應該是從 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 參數(shù)保存了這個程序可以生成的第一個 ASCII 字符,也就是十進制 ASCII 值為 33 的感嘆號。已知該程序生成的隨機數(shù)小于 94,可以計算出生成的最大的 ASCII 值為 93 + 33,等于 126,也就是 ~ 的 ASCII 值。下面的輸出是含有十進制數(shù)值的 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 字符表。
執(zhí)行 generatePassword.go 并傳入合適的命令行參數(shù)將生成如下輸出:
$ 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語言生成隨機數(shù)和隨機字符串的實現(xiàn)方法的文章就介紹到這了,更多相關go語言生成隨機數(shù)和隨機字符串內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
golang通過context控制并發(fā)的應用場景實現(xiàn)
這篇文章主要介紹了golang通過context控制并發(fā)的應用場景實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-01-01