← thecodex.expert · The Codex Family of Knowledge
Tier 1 · Beginner · Go Project

Password Generator

Generate strong, random passwords of any length. Learn secure randomness and building strings from a pool of characters.

🧠 Teaches how to think spoonfed, every age Last verified:

1 The Problem

We want a tool that creates a strong password: a random mix of letters, numbers, and symbols, of a length the user chooses. It teaches building a string from random choices — and an important lesson about which randomness is safe for security.

Where this shows up: password managers, generating API keys, session tokens, temporary access codes, unique IDs. Any time software needs something unpredictable that an attacker cannot guess.

2 How to Think About It

Think about how a strong password is built, before any code:

The plan — in plain English
1. Build a pool of allowed characters (letters + digits + symbols). → 2. Ask how long the password should be. → 3. Pick that many random characters from the pool. → 4. Join them into one string and show it. The key detail: use cryptographically secure randomness, not ordinary randomness.

Build character pool

Ask for length

Pick that many random chars

Join into a password

Show the password

3 The Build — explained part by part

Here is the complete generator. Each part is explained below.

Gopassword.go
package main

import (
	"bufio"
	"crypto/rand"
	"fmt"
	"math/big"
	"os"
	"strconv"
	"strings"
)

const (
	letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
	digits  = "0123456789"
	symbols = "!@#$%^&*"
	pool    = letters + digits + symbols
)

// generate builds a password of the given length from the character pool,
// using crypto/rand — the secure choice for anything security-related.
func generate(length int) string {
	password := make([]byte, length)
	for i := range password {
		// rand.Int never returns an error when reading from crypto/rand.Reader.
		n, _ := rand.Int(rand.Reader, big.NewInt(int64(len(pool))))
		password[i] = pool[n.Int64()]
	}
	return string(password)
}

func main() {
	reader := bufio.NewReader(os.Stdin)
	fmt.Print("Password length: ")
	line, _ := reader.ReadString('\n')
	length, err := strconv.Atoi(strings.TrimSpace(line))
	if err != nil || length <= 0 {
		fmt.Println("Please type a whole number greater than 0.")
		return
	}
	fmt.Printf("Your password: %s\n", generate(length))
}
⚠ No in-browser playground here
Go compiles to a real binary, so unlike the Python version of this project there is no editor above you can run in the browser. Copy the code below and run it on your own machine — it takes seconds once Go is installed.
What each part does — in plain words
crypto/rand, not math/rand — this is the important choice, and it mirrors Python’s secrets vs random exactly. Go has two random packages: math/rand is fast but predictable (fine for games), and crypto/rand reads from the operating system’s secure entropy source, which an attacker cannot predict. Anything security-related — passwords, tokens, session IDs — must use crypto/rand.

const pool = letters + digits + symbols — Go string constants can be built from other constants at compile time, so the whole allowed-character pool is computed once, before the program even runs.

rand.Int(rand.Reader, big.NewInt(n)) — crypto/rand’s API is lower-level than Python’s secrets.choice: it returns a secure random big integer from 0 up to (but not including) n, which is exactly what we need to pick a random index into the pool. math/big is required because cryptographic randomness in Go is built around arbitrary-precision integers.

make([]byte, length) then filling it in a loop — build the password one secure character at a time, the same repeat-length-times idea as Python’s generator expression, just spelled as an explicit loop.
Common mistakes — and how to avoid them
✗ Using math/rand instead of crypto/rand — ordinary random is seeded predictably and unsafe for anything security-related.
✓ Always import crypto/rand for passwords, tokens, or keys.
✗ Ignoring the error from rand.Int in real production code — here it practically never fails, but silently discarding errors is a habit worth catching early.
✓ In code that matters, check the error and fail loudly rather than continuing with a zero value.
✗ Building the pool with only letters — weak passwords.
✓ Include letters, digits, and symbols for strength, as the pool constant above does.

4 Test & Prove Each Part

We cannot predict a random password, but we can prove the rules it must always follow.

A password of length 12 has exactly 12 characters
Every character comes from the allowed pool
Two generated passwords are different (practically always)
Gopassword_test.go
package main

import (
	"strings"
	"testing"
)

func TestCorrectLength(t *testing.T) {
	if got := len(generate(12)); got != 12 {
		t.Errorf("len(generate(12)) = %d; want 12", got)
	}
}

func TestCharsFromPool(t *testing.T) {
	pw := generate(50)
	for _, ch := range pw {
		if !strings.ContainsRune(pool, ch) {
			t.Errorf("character %q in password is not in the allowed pool", ch)
		}
	}
}

func TestPasswordsDiffer(t *testing.T) {
	if generate(16) == generate(16) {
		t.Errorf("two 16-character passwords were identical — extremely unlikely, check the randomness source")
	}
}

Run with go test -v ./.... We test the guarantees: correct length, only allowed characters, and uniqueness — we cannot test the exact output, which is the whole point of randomness. strings.ContainsRune checks each generated character is one we actually allowed.

5 The Interface

INPUTlengtha whole number
What it expects
Password length: 16
OUTPUTpasswordrandom secure string
What it returns
Your password: Rxp7QarCT*DvpdFA

6 Run It & Automate It

Save the code as password.go and run it with go run password.go — Go compiles and executes in one step, no separate build needed while you are experimenting.

Run it locally
go run password.go
Enter a length and get a strong, secure password.

A CI tool like Jenkins runs go test automatically whenever the code changes — every line below has a plain explanation.

What you should see when it works
Terminala real run
Password length: 16
Your password: Rxp7QarCT*DvpdFA
If it breaks — how to fix it
🚨 Please type a whole number greater than 0.
You typed something that is not a positive whole number, or left it blank. Type a number like 16.
🚨 The password looks the same every time I run it.
You are probably using math/rand without noticing, or reusing a fixed seed somewhere. Use crypto/rand as shown above — it never needs seeding.
GroovyJenkinsfile
// Jenkinsfile — runs the tests automatically every time the code changes.
pipeline {
    agent any                                  // run on any available machine

    stages {
        stage('Get the code') {
            steps { checkout scm }             // download the latest code
        }
        stage('Set up Go') {
            steps {
                sh 'go version'                                 // confirm Go is installed
                sh 'test -f go.mod || go mod init password_generator'  // create a module if none exists
            }
        }
        stage('Run the tests') {
            steps {
                sh 'go vet ./...'                    // catch obvious mistakes before running
                sh 'go test -v ./...'                // run every test, show each result
            }
        }
    }

    post {
        success { echo 'All tests passed.' }
        failure { echo 'A test failed — look above.' }
    }
}
🎯 Try this next — make it yours
  1. Guarantee variety. Ensure at least one digit and one symbol by checking after generating (retry if missing). (Teaches: checking conditions.)
  2. Strength meter. Rate the password weak/strong by length with a switch. (Teaches: branching on rules.)
  3. Flag-based length. Use the flag package so you can run ./password -length 20 without a prompt. (Teaches: command-line flags.)
What you learned
You learned to build a string from secure random choices, work with Go’s two random packages, and — most importantly — always reach for crypto/rand (never math/rand) for anything security-related. Related: Standard Library, Error Handling & the Standard Library.