在Go中,我只想要一个随机字符串(大写或小写),没有数字。最快最简单的方法是什么?


当前回答

package main

import (
    "encoding/base64"
    "fmt"
    "math/rand"
    "time"
)

// customEncodeURL is like `bas64.encodeURL` 
// except its made up entirely of uppercase characters:
const customEncodeURL = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKL"

// Random generates a random string.
// It is not cryptographically secure.
func Random(n int) string {
    b := make([]byte, n)
    rand.Seed(time.Now().UnixNano())
    _, _ = rand.Read(b) // docs say that it always returns a nil error.

    customEncoding := base64.NewEncoding(customEncodeURL).WithPadding(base64.NoPadding)
    return customEncoding.EncodeToString(b)
}

func main() {
    fmt.Println(Random(16))
}

其他回答

作为icza的出色解决方案的后续,下面我使用rand。读者

func RandStringBytesMaskImprRandReaderUnsafe(length uint) (string, error) {
    const (
        charset     = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
        charIdxBits = 6                  // 6 bits to represent a letter index
        charIdxMask = 1<<charIdxBits - 1 // All 1-bits, as many as charIdxBits
        charIdxMax  = 63 / charIdxBits   // # of letter indices fitting in 63 bits
    )

    buffer := make([]byte, length)
    charsetLength := len(charset)
    max := big.NewInt(int64(1 << uint64(charsetLength)))

    limit, err := rand.Int(rand.Reader, max)
    if err != nil {
        return "", err
    }

    for index, cache, remain := int(length-1), limit.Int64(), charIdxMax; index >= 0; {
        if remain == 0 {
            limit, err = rand.Int(rand.Reader, max)
            if err != nil {
                return "", err
            }

            cache, remain = limit.Int64(), charIdxMax
        }

        if idx := int(cache & charIdxMask); idx < charsetLength {
            buffer[index] = charset[idx]
            index--
        }

        cache >>= charIdxBits
        remain--
    }

    return *(*string)(unsafe.Pointer(&buffer)), nil
}


func BenchmarkBytesMaskImprRandReaderUnsafe(b *testing.B) {
    b.ReportAllocs()
    b.ResetTimer()

    const length = 16

    b.RunParallel(func(pb *testing.PB) {
        for pb.Next() {
            RandStringBytesMaskImprRandReaderUnsafe(length)
        }
    })
}
package main

import (
    "encoding/base64"
    "fmt"
    "math/rand"
    "time"
)

// customEncodeURL is like `bas64.encodeURL` 
// except its made up entirely of uppercase characters:
const customEncodeURL = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKL"

// Random generates a random string.
// It is not cryptographically secure.
func Random(n int) string {
    b := make([]byte, n)
    rand.Seed(time.Now().UnixNano())
    _, _ = rand.Read(b) // docs say that it always returns a nil error.

    customEncoding := base64.NewEncoding(customEncodeURL).WithPadding(base64.NoPadding)
    return customEncoding.EncodeToString(b)
}

func main() {
    fmt.Println(Random(16))
}
func Rand(n int) (str string) {
    b := make([]byte, n)
    rand.Read(b)
    str = fmt.Sprintf("%x", b)
    return
}

简单的解决方案,最少重复的结果:

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

func randomString(length int) string {
    rand.Seed(time.Now().UnixNano())
    b := make([]byte, length+2)
    rand.Read(b)
    return fmt.Sprintf("%x", b)[2 : length+2]
}

在操场上看看

这是一个示例代码,我用来生成证书号码在我的应用程序。

func GenerateCertificateNumber() string {
    CertificateLength := 7
    t := time.Now().String()
    CertificateHash, err := bcrypt.GenerateFromPassword([]byte(t), bcrypt.DefaultCost)
    if err != nil {
        fmt.Println(err)
    }
    // Make a Regex we only want letters and numbers
    reg, err := regexp.Compile("[^a-zA-Z0-9]+")
    if err != nil {
        log.Fatal(err)
    }
    processedString := reg.ReplaceAllString(string(CertificateHash), "")
    fmt.Println(string(processedString))

    CertificateNumber := strings.ToUpper(string(processedString[len(processedString)-CertificateLength:]))
    fmt.Println(CertificateNumber)
    return CertificateNumber
}