用GO生成指定长度的随机字符串

搜索关键字:

golang fixed length random string

参考解答:

常规的比较容易想到的方案(从目标字符集中随机选出N个字符组成字符串):

package main

import (
    "fmt"
    "math/rand"
)

var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")

func randSeq(n int) string {
    b := make([]rune, n)
    for i := range b {
        b[i] = letters[rand.Intn(len(letters))]
    }
    return string(b)
}

func main() {
    fmt.Println(randSeq(10))
}



从简单方案开始进行的一次优化历程:

// 将rune数组用byte数组替换
// var lettersB = []bytes("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")

// 将rune数组用字符串常量替换
const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"

func RandStringBytes(n int) string {
	b := make([]byte, n)
	for i := range b {
		b[i] = letterBytes[rand.Intn(len(letterBytes))]
	}
	return string(b)
}

// 用rand.Int63()替换rand.Intn()
func RandStringBytesRmndr(n int) string {
	b := make([]byte, n)
	for i := range b {
		b[i] = letterBytes[rand.Int63()%int64(len(letterBytes))]
	}
	return string(b)
}

// 用掩码进行替换
const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
const (
    letterIdxBits = 6                    // 6 bits to represent a letter index
    letterIdxMask = 1<= 0; {
        if remain == 0 {
            cache, remain = rand.Int63(), letterIdxMax
        }
        if idx := int(cache & letterIdxMask); idx < len(letterBytes) {
            b[i] = letterBytes[idx]
            i--
        }
        cache >>= letterIdxBits
        remain--
    }

    return string(b)
}


上面的方法用的都是”math/rand”提供(伪)随机数,如果对随机性有高要求的话,可以用”crypto/rand”实现(速度相对来说会慢些):


// Reference: https://github.com/dchest/uniuri/blob/master/uniuri.go
package main

import (
    "crypto/rand"
    "fmt"
)

const (
    StdLen  = 16
    UUIDLen = 20
)

var StdChars = []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")
// var AsciiChars = []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()-_=+,.?/:;{}[]`~")

func main() {
    fmt.Printf("%s\n", New())
    fmt.Printf("%s\n", New())

    fmt.Printf("%s\n", NewLen(8))
    fmt.Printf("%s\n", NewLen(8))
}

func New() string {
    return NewLenChars(StdLen, StdChars)
}

func NewLen(length int) string {
    return NewLenChars(length, StdChars)
}

// NewLenChars returns a new random string of the provided length, consisting of the provided byte slice of allowed characters(maximum 256).
func NewLenChars(length int, chars []byte) string {
    if length == 0 {
        return ""
    }
    clen := len(chars)
    if clen < 2 || clen > 256 {
        panic("Wrong charset length for NewLenChars()")
    }
    maxrb := 255 - (256 % clen)
    b := make([]byte, length)
    r := make([]byte, length+(length/4)) // storage for random bytes.
    i := 0
    for {
        if _, err := rand.Read(r); err != nil {
            panic("Error reading random bytes: " + err.Error())
        }
        for _, rb := range r {
            c := int(rb)
            if c > maxrb {
                continue // Skip this number to avoid modulo bias.
            }
            b[i] = chars[c%clen]
            i++
            if i == length {
                return string(b)
            }
        }
    }
}





还有一个比较偏门的方法就是用哈希值来表示随机字符串:


// create random passwd
func createPasswd() string {
    t := time.Now()
    h := md5.New()
    io.WriteString(h, "crazyof.me")
    io.WriteString(h, t.String())
    passwd := fmt.Sprintf("%x", h.Sum(nil))
    return passwd
}




原文链接:https://crazyof.me/blog/archives/2535.html



你可能感兴趣的:(用GO生成指定长度的随机字符串)