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.
- 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
# Create a new project
mkdir my-api
cd my-api
go mod init my-api
# Install Mux
go get github.com/fgrzl/muxCreate 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)
}
}go run .curl http://localhost:8080/Expected output:
{
"message": "Welcome to my API!",
"status": "running"
}Congratulations! You have a working API!
Choose your own adventure:
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
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)
Cheat Sheet - Quick reference for common patterns
Perfect for experienced developers who just need syntax examples.
Examples Directory - Working applications
- hello-world: Minimal example
- todo-api: Full CRUD API with OpenAPI docs
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
Before diving deeper, understand these key concepts:
The router matches HTTP requests to handlers:
router := mux.NewRouter()
router.GET("/users", listUsers) // Match GET /users
router.POST("/users", createUser) // Match POST /usersEvery 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})
}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)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/usersProduction-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
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)
})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)
})router.GET("/search", func(c mux.RouteContext) {
query, _ := c.Query().String("q")
limit, _ := c.Query().Int("limit")
results := search(query, limit)
c.OK(results)
})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)
})// 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()
})# Run with auto-reload (using air)
go install github.com/cosmtrek/air@latest
air
# Or run manually
go run .# Run tests
go test ./...
# With coverage
go test ./... -cover
# Verbose output
go test ./... -v# Build binary
go build -o myapi
# Run binary
./myapi
# Build for production (smaller binary)
CGO_ENABLED=0 go build -ldflags="-s -w" -o myapi# 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
# - KubernetesProblem: Import errors when running code
Solution:
go mod tidy
go get github.com/fgrzl/muxProblem: Routes not matching as expected
Solutions:
- Check HTTP method matches (GET vs POST)
- Verify path exactly matches (case-sensitive)
- Ensure your
mux.Routeris the handler passed tomux.NewServer(...)or a customhttp.Server
Problem: c.Bind() failing
Solutions:
- Verify
Content-Type: application/jsonheader is set - Check JSON syntax with a validator
- Ensure struct fields are exported (capitalized)
Problem: Struct fields not serializing
Solutions:
- Capitalize field names (exported fields only)
- Add JSON tags:
json:"fieldName" - Check for
json:"-"tags that hide fields
You're ready to build! Here are your best next steps:
- Complete the Interactive Tutorial
- Customize the Todo API example
- Build your own API
- Follow the Learning Path from Level 1
- Read each level's documentation
- Complete the exercises at each level
- Bookmark the Cheat Sheet
- Keep the API Reference handy
- Browse the examples directory
| 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 |
- Documentation: Check the docs directory
- Issues: GitHub Issues
- Examples: Browse examples
- API Reference: pkg.go.dev
- Use route groups - Organize routes logically and avoid repetition
- Enable logging early -
mux.UseLogging(router)helps debugging - Document as you go - Add OpenAPI metadata while writing handlers
- Test incrementally - Test each endpoint before moving to the next
- Read the examples - They demonstrate best practices
Ready to build something amazing? Let's go!
Start with the Interactive Tutorial
- Quick Start - Get running in 5 minutes
- Interactive Tutorial - Build a Todo API
- Learning Path - Structured learning progression
- Cheat Sheet - Quick reference guide
- Router - Routing fundamentals
- Middleware - Built-in middleware guide