Skip to content

Guide

This guide covers all the core concepts of Marten in depth.

Core Concepts

  • Routing


    Learn about static routes, path parameters, wildcards, and HTTP methods.

    Routing

  • Context


    The request context provides helpers for params, queries, binding, and responses.

    Context

  • Middleware


    Add cross-cutting concerns like logging, auth, and rate limiting.

    Middleware

  • Route Groups


    Organize routes with shared prefixes and middleware.

    Route Groups

  • Error Handling


    Handle errors gracefully with custom error handlers.

    Error Handling

  • Testing


    Write tests for your Marten applications.

    Testing

Architecture Overview

graph LR
    A[Request] --> B[Global Middleware]
    B --> C[Router]
    C --> D[Route Middleware]
    D --> E[Handler]
    E --> F[Response]
  1. Request arrives at the server
  2. Global Middleware processes the request (logging, recovery, etc.)
  3. Router matches the path and method to a handler
  4. Route Middleware runs (auth, validation, etc.)
  5. Handler processes the request and returns a response
  6. Response is sent back through the middleware chain

The App

Everything starts with creating an app:

app := marten.New()

The app is the central object that:

  • Holds the router
  • Manages middleware
  • Implements http.Handler
  • Provides graceful shutdown

The Context

Every handler receives a context (*marten.Ctx) that wraps the request and response:

func handler(c *marten.Ctx) error {
    // Access request
    method := c.Method()
    path := c.Path()

    // Get parameters
    id := c.Param("id")
    page := c.QueryInt("page")

    // Bind JSON
    var data MyStruct
    c.Bind(&data)

    // Send response
    return c.OK(data)
}

Handlers

Handlers are functions that process requests:

type Handler func(*Ctx) error

Returning an error triggers the error handler:

func getUser(c *marten.Ctx) error {
    user, err := findUser(c.Param("id"))
    if err != nil {
        return err // Triggers error handler
    }
    return c.OK(user)
}

Middleware

Middleware wraps handlers to add functionality:

type Middleware func(Handler) Handler

Example:

func Timer(next marten.Handler) marten.Handler {
    return func(c *marten.Ctx) error {
        start := time.Now()
        err := next(c)
        log.Printf("Request took %v", time.Since(start))
        return err
    }
}

Next Steps

Start with Routing to learn how to define your API endpoints.