Golang Random String Generator | srgdev.com

Golang Random String Generator

High performance golang random string generator. The default 'rand.Source' is used, therefore the code is safe for concurrent use by multiple goroutines.Golang, gobench Download: rndstr.go

About

This code is largely based on this StackOverflow answer. The default Source of uniformly-distributed pseudo-random values is seeded at package init() with a time.Now().UnixNano() Returned value can contain any of these 64 characters:

1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_
gobench @see rndstr_test.go:
goos: linux
goarch: amd64
pkg: rndstr
BenchmarkGetBytes48-4     	10000000	 176 ns/op		  48 B/op	1 allocs/op
BenchmarkGetBytes1500-4   	  300000	4863 ns/op		1536 B/op	1 allocs/op
PASS

rndstr.go

// A fast random []byte generator. The default Source is used, which
// is safe for concurrent use by multiple goroutines. The default Source
// is seeded at package init.
package rndstr

import (
  "math/rand"
  "time"
)

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

const letterBytes = "1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_"
const (
  letterIdxBits = 6                    // 6 bits to represent a letter index
  letterIdxMask = 1<<letterIdxBits - 1 // All 1-bits, as many as letterIdxBits
  letterIdxMax  = 63 / letterIdxBits   // # of letter indices fitting in 63 bits
)

// Fills the []byte with random characters
func PutBytes(b []byte) {
  n := len(b)
  for i, cache, remain := n-1, rand.Int63(), letterIdxMax; i >= 0; {
    if remain == 0 {
      cache, remain = rand.Int63(), letterIdxMax
    }
    idx := int(cache & letterIdxMask)
    b[i] = letterBytes[idx]
    i--
    cache >>= letterIdxBits
    remain--
  }
}

// Returns []byte of 'n' length filled with random characters
func GetBytes(n int) []byte {
  b := make([]byte, n)
  PutBytes(b)
  return b
}

rndstr_test.go

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package rndstr import "testing" func TestGetBytes(t *testing.T) { randomBytes := GetBytes(1064) t.Logf("%s", randomBytes) } func TestPutBytes(t *testing.T) { randomBytes := make([]byte, 72) PutBytes(randomBytes) t.Logf("%s", randomBytes) } var result []byte func BenchmarkGetBytes48(b *testing.B) { b.ReportAllocs() var r []byte for n := 0; n < b.N; n++ { r = GetBytes(48) } result = r } func BenchmarkGetBytes1500(b *testing.B) { b.ReportAllocs() var r []byte for n := 0; n < b.N; n++ { r = GetBytes(1500) } result = r }