Skip to content

Latest commit

 

History

History
478 lines (345 loc) · 9.99 KB

File metadata and controls

478 lines (345 loc) · 9.99 KB

Getting Started with Mux

Welcome! This guide will get you from zero to a working API in minutes. Mux is designed as a fast, batteries-included framework, so the path here starts with its integrated router, server lifecycle, and response helpers instead of assembling separate packages.

Prerequisites

  • Go 1.25.6 or later - Download here
  • Basic Go knowledge - Understand functions, structs, and packages
  • A code editor - VS Code, GoLand, or your favorite editor

Quick Start (5 Minutes)

1. Install Mux

# Create a new project
mkdir my-api
cd my-api
go mod init my-api

# Install Mux
go get github.com/fgrzl/mux

2. Create Your First API

Create main.go:

package main

import (
    "context"
    "os"
    "os/signal"
    "syscall"

    "github.com/fgrzl/mux"
)

func main() {
    router := mux.NewRouter()

    if err := router.Configure(func(router *mux.Router) {
        router.GET("/", func(c mux.RouteContext) {
            c.OK(map[string]string{
                "message": "Welcome to my API!",
                "status":  "running",
            })
        })
    }); err != nil {
        panic(err)
    }

    ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
    defer stop()

    server := mux.NewServer(":8080", router)
    if err := server.Listen(ctx); err != nil {
        panic(err)
    }
}

3. Run It!

go run .

4. Test It!

curl http://localhost:8080/

Expected output:

{
  "message": "Welcome to my API!",
  "status": "running"
}

Congratulations! You have a working API!


What's Next?

Choose your own adventure:

Option 1: Learn by Doing (Recommended)

Interactive Tutorial - Build a complete Todo API in 30 minutes

This hands-on tutorial will teach you:

  • CRUD operations
  • JSON handling
  • Validation
  • Error handling
  • OpenAPI documentation

Option 2: Structured Learning

Learning Path - Progressive 8-level course

Start at your level:

  • Beginner: Levels 1-3 (basic routing and parameters)
  • Intermediate: Levels 4-6 (groups, middleware, OpenAPI)
  • Advanced: Levels 7-8 (error handling, production)

Option 3: Copy & Paste

Cheat Sheet - Quick reference for common patterns

Perfect for experienced developers who just need syntax examples.

Option 4: See Complete Examples

Examples Directory - Working applications

  • hello-world: Minimal example
  • todo-api: Full CRUD API with OpenAPI docs

Roadmap

Here's a typical learning progression:

Day 1: Hello World + Basic Routes (30 min)
  |
Day 2: JSON APIs + Path Parameters (1 hour)
  |
Day 3: Middleware + Authentication (1 hour)
  |
Day 4: OpenAPI Documentation (30 min)
  |
Day 5: Production Deployment (1 hour)

Total investment: ~4-5 hours to full proficiency


Core Concepts

Before diving deeper, understand these key concepts:

1. Router

The router matches HTTP requests to handlers:

router := mux.NewRouter()
router.GET("/users", listUsers)    // Match GET /users
router.POST("/users", createUser)  // Match POST /users

2. RouteContext

Every handler receives a RouteContext with request data and response helpers:

func myHandler(c mux.RouteContext) {
    // Read request
    name, _ := c.Params().String("name")
    
    // Send response
    c.OK(map[string]string{"hello": name})
}

3. Middleware

Middleware runs before handlers to add cross-cutting functionality:

// Add logging to all routes
mux.UseLogging(router)

// Add authentication to specific routes
api := router.Group("/api")
api.Use(authMiddleware)

4. Route Groups

Organize related routes with shared configuration:

api := router.Group("/api/v1")
api.WithTags("API v1")

users := api.Group("/users")
users.GET("/", listUsers)
users.POST("/", createUser)
// Results in: /api/v1/users

5. WebServer (Production)

Production-ready server with graceful shutdown and TLS:

import (
    "context"
    "os"
    "os/signal"
    "syscall"

    "github.com/fgrzl/mux"
)

router := mux.NewRouter()

if err := router.Configure(func(router *mux.Router) {
    // Register routes and groups here.
}); err != nil { panic(err) }

server := mux.NewServer(":8080", router)

ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer cancel()

if err := server.Listen(ctx); err != nil { panic(err) }

Features:

  • Automatic graceful shutdown
  • Production-ready timeouts (10s read/write, 120s idle)
  • TLS/HTTPS support
  • Context-based lifecycle

Common Patterns

Pattern 1: JSON API

type User struct {
    ID    string `json:"id"`
    Name  string `json:"name"`
    Email string `json:"email"`
}

router.POST("/users", func(c mux.RouteContext) {
    var user User
    if err := c.Bind(&user); err != nil {
        c.BadRequest("Invalid JSON", err.Error())
        return
    }
    
    c.Created(user)
})

Pattern 2: Path Parameters

router.GET("/users/{id}", func(c mux.RouteContext) {
    id, ok := c.Params().String("id")
    if !ok {
        c.BadRequest("Missing parameter", "id is required")
        return
    }
    
    user := fetchUser(id)
    c.OK(user)
})

Pattern 3: Query Parameters

router.GET("/search", func(c mux.RouteContext) {
    query, _ := c.Query().String("q")
    limit, _ := c.Query().Int("limit")
    
    results := search(query, limit)
    c.OK(results)
})

Pattern 4: Error Handling

router.GET("/users/{id}", func(c mux.RouteContext) {
    id, _ := c.Params().String("id")
    
    user, err := fetchUser(id)
    if err == ErrNotFound {
        c.NotFound()
        return
    }
    if err != nil {
        c.ServerError("Database error", err.Error())
        return
    }
    
    c.OK(user)
})

Pattern 5: Health Checks (Kubernetes-style)

// Built-in probe endpoints (automatically allow anonymous access)
router.Healthz()  // GET /healthz - simple health check
router.Livez()    // GET /livez - liveness probe
router.Readyz()   // GET /readyz - readiness probe

// With custom checks
router.ReadyzWithCheck(func(c mux.RouteContext) bool {
    // Returns 200 OK if ready, 503 Service Unavailable if not
    return db.Ping() == nil && cache.Ready()
})

Development Workflow

1. Local Development

# Run with auto-reload (using air)
go install github.com/cosmtrek/air@latest
air

# Or run manually
go run .

2. Testing

# Run tests
go test ./...

# With coverage
go test ./... -cover

# Verbose output
go test ./... -v

3. Building

# Build binary
go build -o myapi

# Run binary
./myapi

# Build for production (smaller binary)
CGO_ENABLED=0 go build -ldflags="-s -w" -o myapi

4. Deployment

# Docker
docker build -t myapi .
docker run -p 8080:8080 myapi

# Or deploy to your favorite platform
# - Heroku, Railway, Fly.io
# - AWS Lambda, Google Cloud Run
# - Kubernetes

Troubleshooting

"cannot find package"

Problem: Import errors when running code

Solution:

go mod tidy
go get github.com/fgrzl/mux

"404 Not Found" for valid routes

Problem: Routes not matching as expected

Solutions:

  • Check HTTP method matches (GET vs POST)
  • Verify path exactly matches (case-sensitive)
  • Ensure your mux.Router is the handler passed to mux.NewServer(...) or a custom http.Server

"Invalid JSON" errors

Problem: c.Bind() failing

Solutions:

  • Verify Content-Type: application/json header is set
  • Check JSON syntax with a validator
  • Ensure struct fields are exported (capitalized)

JSON fields not appearing in response

Problem: Struct fields not serializing

Solutions:

  • Capitalize field names (exported fields only)
  • Add JSON tags: json:"fieldName"
  • Check for json:"-" tags that hide fields

Next Steps

You're ready to build! Here are your best next steps:

For Hands-On Learners

  1. Complete the Interactive Tutorial
  2. Customize the Todo API example
  3. Build your own API

For Systematic Learners

  1. Follow the Learning Path from Level 1
  2. Read each level's documentation
  3. Complete the exercises at each level

For Quick Reference

  1. Bookmark the Cheat Sheet
  2. Keep the API Reference handy
  3. Browse the examples directory

Learning Resources Summary

Resource Best For Time
Interactive Tutorial Hands-on learners 30 min
Learning Path Structured progression 2 hours
Cheat Sheet Quick reference 5 min
Hello World Example Verify setup 5 min
Todo API Example Complete reference 15 min

Get Help


Pro Tips

  1. Use route groups - Organize routes logically and avoid repetition
  2. Enable logging early - mux.UseLogging(router) helps debugging
  3. Document as you go - Add OpenAPI metadata while writing handlers
  4. Test incrementally - Test each endpoint before moving to the next
  5. Read the examples - They demonstrate best practices

Ready to build something amazing? Let's go!

Start with the Interactive Tutorial

See Also