⭐ 10 General Go Mini-Projects (Non-Web, Non-Backend)

Perfect — here are 10 Go mini-projects focused ONLY on general programming, no web, no APIs, no backend.
These improve pure Go skills: data structures, concurrency, file handling, algorithms, CLI tools, etc

1. Random Password Generator (Done)
Skills: strings, randomness, slices, crypto/rand, functions.

2. Text File Word Counter

Read a .txt file and print:

  • total words
  • total lines
  • most common word

Skills: file reading (os, bufio), maps, string processing, counting algorithms.


3. Simple CLI Calculator

Accept command-line input:
go run main.go add 10 3

Supports: add, subtract, multiply, divide.

Skills: CLI arguments (os.Args), parsing, error handling.

4. Contact Book (Stored in JSON File) Features:

  • Add contact
  • List contacts
  • Delete contact

Save everything in contacts.json.

Skills: JSON, structs, file I/O, slices.

5. Todo App in Terminal (Persistent)

Store tasks in a JSON or text file.
Commands: add, delete, list, mark-done.

Skills: file writing, slices, struct organization, CLI tools.

6. Concurrency Demo: Goroutine Timer: Create multiple timers that run in parallel.

Example:

  • Timer 1 → prints every 2 seconds
  • Timer 2 → prints every 5 seconds

Skills: goroutines, channels, time package.

7. Sudoku Solver (Backtracking Algorithm): Take a partially filled Sudoku board and solve it.

Skills: 2D arrays, recursion, backtracking, algorithm design.

8. File Encryption / Decryption Tool: Encrypt any text file using XOR or AES (basic version).

Skills: reading binary data, byte slices, basic crypto, command-line usage.

9. Markov Chain Text Generator

Feed a text file (like a book chapter) and generate random sentences like:

“The quick brown fox jumps inside the happy cloud…”

Skills: maps of slices, random selection, string building, algorithms.

10. Basic Image Manipulator (No GUI)

Load a PNG or JPEG and perform operations like:

  • convert to grayscale
  • flip horizontally
  • resize (nearest neighbor)

Skills: Go’s image package, pixel manipulation, file I/O, loops.


Skills You Build Across These Projects

SkillProjects That Teach It
File I/OWord Counter, Contact Book, Todo App, Image Tools
JSONContact Book, Todo App
CLI toolsCalculator, Todo App
ConcurrencyGoroutine Timer
Data structuresSudoku Solver, Markov Generator
AlgorithmsSudoku Solver, Markov Generator
Slices & MapsMost projects
Error handlingAll projects
Crypto & securityPassword Generator, File Encryption

Random Password generator

package main

import ("crypto/rand" "fmt" "math/big")

const (
	uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
	lowercase = "abcdefghijklmnopqrstuvwxyz"
	digits    = "0123456789"
	symbols   = "!@#$%^&*()-_=+[]{}|;:,.<>/?"
)

func randomChar(chars string) (byte, error) {
	max := big.NewInt(int64(len(chars)))
	n, err := rand.Int(rand.Reader, max)
	if err != nil {
		return 0, err
	}
	return chars[n.Int64()], nil
}

func strongPasswordGenerator(length int) (string, error) {
	// Step 1 : Ensure at least one of each
	password := make([]byte, 0, length)

	sets := []string{uppercase, lowercase, digits, symbols}
	for _, set := range sets {
		ch, err := randomChar(set)
		if err != nil {
			return "", err
		}
		password = append(password, ch)
	}

	// Fill remaining characters
	for len(password) < length {
		ch, err := randomChar(allChars)
		if err != nil {
			return "", err
		}
		password = append(password, ch)
	}

	// Shuffle password
	for i := range password {
		jBig, err := rand.Int(rand.Reader, big.NewInt(int64(len(password))))
		if err != nil {
			return "", err
		}
		j := jBig.Int64()

		password[i], password[j] = password[j], password[i]
	}

	return string(password), nil
}

func main() {
	for {
		var length int
		fmt.Print("Enter the password length (min 10): ")

		_, err := fmt.Scan(&length)
		if err != nil {
			fmt.Println("Please enter a valid number.")
			continue
		}

		if length < 10 {
			fmt.Println("Password must be at least 10 characters.")
			continue
		}

		password, err := strongPasswordGenerator(length)
		if err != nil {
			fmt.Println("Error generating password:", err)
			continue
		}

		fmt.Println("Generated Password:", password)

		var choice string
		fmt.Print("Generate another? (yes/no): ")
		fmt.Scan(&choice)

		if choice != "yes" && choice != "y" {
			fmt.Println("Goodbye!")
			break
		}
	}
}

Technical explaination on above code

Here’s a simple, clear explanation for these lines:

max := big.NewInt(int64(len(chars)))
n, err := rand.Int(rand.Reader, max)

✅ What this does

1. max := big.NewInt(int64(len(chars)))

  • len(chars) = how many characters are in the string.
  • big.NewInt() converts that number into a big integer (required by crypto/rand).
  • This tells Go: “pick a number between 0 and len(chars)-1”.

Example:

If chars = "ABC"
Then len(chars) = 3

So:

max = 3  (meaning: pick 0, 1, or 2)

2. n, err := rand.Int(rand.Reader, max)

  • rand.Int generates a cryptographically secure random number.
  • rand.Reader is a secure source of randomness provided by your OS.

In other words:

rand.Reader = strong, system-level randomness
(better than math/rand, which is predictable)

Example output:

If rand.Int(rand.Reader, 3) is called, possible values:

0
1
2

Each value is secure and unpredictable.

✔ If chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"

This string has 26 characters.

1. What is max?

Since len(chars) = 26:

max = 26

👉 This means Go will generate a number in the range:

0 to 25  (inclusive)

✔ What is n?

n, err := rand.Int(rand.Reader, max)

This line generates a secure random integer from:

0 to 25

Examples of possible values of n:

0
13
25
7

Every run gives a different unpredictable value.

✔ Is n a character?

No — n is NOT a character. n is a random index number. Then we use it to pick a character:

chars[n.Int64()]

Example If:

n = 0 → chars[0] = 'A'
n = 5 → chars[5] = 'F'
n = 25 → chars[25] = 'Z'

So the random character comes from:

random index → used to pick a letter

✔ Summary

VariableMeaning
max = 26Size of allowed range
nSecure random number from 0–25
chars[n]Random character from A to Z

✅ What is rand.Reader (in simple words)

rand.Reader is Go’s built-in source of secure random bytes. Think of it like this:

🔐 rand.Reader = a pipe connected to your operating system’s secure randomness

Your OS constantly generates high-quality random data (mouse movement, CPU noise, hardware RNG, etc.). Go exposes this through:

rand.Reader

It’s the trusted source of randomness used in:

  • password generators
  • encryption
  • tokens
  • keys
  • anything security-related

🤔 Why have I not seen this in other languages?

Because most languages hide this behind a single function:

LanguageSecure random function
Pythonsecrets.token_bytes()
JavaScriptcrypto.getRandomValues()
RustOsRng
JavaSecureRandom
C#RNGCryptoServiceProvider

They also use the OS’s secure randomness—just not as obviously. Go chooses to show it explicitly:

rand.Reader  // ← secure random source

This gives the developer more control and makes it clear that the randomness is cryptographically secure.

✔ Why do we need rand.Reader?

Because math/rand is predictable, meaning:

❌ It can be guessed
❌ It can be repeated
❌ It is unsafe for passwords or keys

But:

crypto/rand (with rand.Reader) produces randomness that cannot be predicted.

Example:

rand.Int(rand.Reader, max)

This tells Go:

“Use secure randomness to generate a number from 0 to max-1.”

📌 Simple Analogy

  1. math/rand = dice in your hand (predictable)
  2. rand.Reader = casino-grade dice machine (unpredictable, safe)

For passwords, keys, tokens → you need the casino machine.

✔ Tiny example

b := make([]byte, 5)
rand.Reader.Read(b)
fmt.Println(b)

This prints 5 secure random bytes (different every time

Scroll to Top