go

Go, create a Unicode random string generator
🥺😂🥰😊😍😊😝🤗abcdefghijklmnopqrstuvwxyz

Reading time of 517 words
3 minutes
Reading time of 517 words ~ 3 minutes


If you find this content useful, consider buying me a coffee
Or help me out by engaging with any advertisers that you find interesting

One of the great things about the Go standard library is how easy it is to create a sophisticated tool using a small amount of code. In this entry, I will explain how to make a variable-length random string generator that can support any Unicode character.

You can find the final result on GitHub or run it at Go Playground.

First, we create a constant containing a collection of Unicode characters that will be used by the randomiser.

const random string = "🥺😂🥰😊😍😊😝🤗abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0987654321 .!?"

The function will require int argument for the length of the returned string and a returned error.

// randString generates a random string of n x characters.
func randString(n int) (string, error) {
    return "", nil
}

The s rune slice will contain and return the random characters as a string. Using make we pre-allocate the total number of returned runes (Unicode characters).

s := make([]rune, n)

Convert the random const into a rune array.

r := []rune(random)

Declare the variables.

// randString generates a random string of n x characters.
func randString(n int) (string, error) {
    s, r := make([]rune, n), []rune(random)
    return "", nil
}

We now loop over the empty rune slice where its index position is the i variable.

// randString generates a random string of n x characters.
func randString(n int) (string, error) {
    s, r := make([]rune, n), []rune(random)
    for i := range s {}
    return "", nil
}

In each loop iteration, generate a new random big integer using Prime from the crypto/rand library. The library will satisfy any security concerns with gosec or other linters.

// randString generates a random string of n x characters.
func randString(n int) (string, error) {
    s, r := make([]rune, n), []rune(random)
    for i := range s {
        p, err := rand.Prime(rand.Reader, len(r))
        if err != nil {
            return "", fmt.Errorf("random string n %d: %w", n, err)
        }
    }
    return "", nil
}

Convert the randomly generated big integer into an unsigned 64-bit integer and save it to x.

x := p.Uint64()

Count the number of random characters and save the result as an unsigned 64-bit integer.

y := uint64(len(r))

Using the modulo operator %, we find the remainder of x / y and use that value as the index to fetch a random character from our slice of characters. The fetched character gets appended to our return string until the loop finishes.

// randString generates a random string of n x characters.
func randString(n int) (string, error) {
    s, r := make([]rune, n), []rune(random)
    for i := range s {
        p, err := rand.Prime(rand.Reader, len(r))
        if err != nil {
            return "", fmt.Errorf("random string n %d: %w", n, err)
        }
        x, y := p.Uint64(), uint64(len(r))
        s[i] = r[x%y]
    }
    return "", nil
}

If you want to visualise the process, then printf the variable results within the loop and run it in Go Playground.

fmt.Printf("x: %d y: %d\tx %% y = %d\trandom[%d] = %q\n", x, y, x%y, x%y, string(r[x%y]))

Otherwise, we now have a functional string randomiser.

# 1st go.
p😂H🤗😊JL7😊J9zPD9LFPTB

# 2nd go.
XZff1tzV😂Vx😊bPbvhpV😊

# 3rd go.
fn😂vbF5.FN3XZ😊5Vb😂Z.

Written by Ben Garrett

If you find this content useful, consider buying me a coffee
Or help me out by engaging with any advertisers that you find interesting