Go

Go, create a Unicode random string generator.


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.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s