高性能 golang 生成指定長度隨機字符串

先直接貼代碼吧。

package main

import (
	"math/rand"
	"time"
)

var letters = []byte("abcdefghjkmnpqrstuvwxyz123456789")
var longLetters = []byte("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ=_")

func init() {
	rand.Seed(time.Now().Unix())
}

// RandLow 隨機字符串,包含 1~9 和 a~z - [i,l,o]
func RandLow(n int) []byte {
	if n <= 0 {
		return []byte{}
	}
	b := make([]byte, n)
	arc := uint8(0)
	if _, err := rand.Read(b[:]); err != nil {
		return []byte{}
	}
	for i, x := range b {
		arc = x & 31
		b[i] = letters[arc]
	}
	return b
}

// RandUp 隨機字符串,包含 英文字母和數字附加=_兩個符號
func RandUp(n int) []byte {
	if n <= 0 {
		return []byte{}
	}
	b := make([]byte, n)
	arc := uint8(0)
	if _, err := rand.Read(b[:]); err != nil {
		return []byte{}
	}
	for i, x := range b {
		arc = x & 63
		b[i] = longLetters[arc]
	}
	return b
}

// RandHex 生成16進制格式的隨機字符串
func RandHex(n int) []byte {
	if n <= 0 {
		return []byte{}
	}
	var need int
	if n & 1 == 0 { // even
		need = n
	} else { // odd
		need = n + 1
	}
	size := need / 2
	dst := make([]byte, need)
	src := dst[size:]
	if _, err := rand.Read(src[:]); err != nil {
		return []byte{}
	}
	hex.Encode(dst, src)
	return dst[:n]
}

現在來解釋一下。網上很多代碼生成隨機字符串的方法,反覆調用 rand 隨機函數。實際上。rand 的隨機函數本身也是調用的系統函數,開銷根據操作系統而定。應儘量少調用。本系列方法思路是,一次隨機出足夠多的數據,然後挨個填充。

比如,需要生成長度爲 n 的字符串,我就直接使用 make 申請足夠空間 b := make([]byte, n), 然後使用 rand.Read(b[:]) 將此空間填滿,本來這算是可以了,但是由於 b 中包含各種奇奇怪怪的字符,我們需要控制一下輸出內容。因此可以根據隨機生成的內容,再挨個替換掉。b[i] = letters[arc] 就是負責內容替換的。x 是原先隨機生成的 byte 內容,對應的10進制範圍是 0-255。不過我們需要生成的字符個數,只要 32 或者 64 個,因此我們需要對 x 轉化到 32 或者 64 以下的值,最快就是進行 & 或者 ^ 運算。到底選用哪個都無所謂。這樣我們就快速地替換了隨機內容。

如果是隻生成0-9 a-f 內容的隨機字符串,那就容易了。如這裏的 RanHex 方法

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章