Guide · Open source
How to use chi: a Go router tutorial
Updated · written with AI from the project's own documentation and checked against our catalogue data
chi is a routing library for Go. It maps incoming web requests to the functions that should handle them, such as sending GET /articles/123 to a function that loads article 123. This guide shows you how to install chi, register routes, add middleware, organize routes with groups and sub-routers, and read URL parameters, so you can structure a REST API that stays manageable as it grows.
Quick start
- 1Install chi. Run go get -u github.com/go-chi/chi/v5 inside your Go module.
- 2Create a router. Call chi.NewRouter() to create the router that holds your routes.
- 3Add middleware. Attach middleware such as middleware.Logger with r.Use.
- 4Register routes. Use r.Get, r.Post, r.Put or r.Delete with a URL pattern and a handler.
- 5Group routes. Use r.Route for a sub-router under a path and r.Mount to attach another handler.
- 6Read URL parameters. Use chi.URLParam(r, "name") inside a handler to get a value such as an article ID.
- 7Start the server. Pass the router to http.ListenAndServe, since chi's router implements http.Handler.
What chi is and who it is for
chi is a lightweight, idiomatic and composable router for building Go HTTP services. It is built on Go's standard net/http package and the context package, so handlers and middleware written for the standard library generally work with it.
It is aimed at larger REST API projects that need to stay organized as they grow. chi covers routing only. If you want templates, an ORM or built-in authentication, you will need separate packages for those.
- Good fit: Go developers building REST API services, teams that want routing on the standard library, and projects that need route groups, nested sub-routers or mounted handlers.
- Not a fit: people who want a full web framework, people not writing Go, and beginners without Go experience, since the README assumes you already understand Go handlers and context.
Install chi in a Go project
chi is installed with the Go toolchain. The README gives the command below for chi v5. It does not specify a minimum Go version, so check the project's documentation if you need one.
Run the command inside your Go module, then import the packages you use.
go get -u github.com/go-chi/chi/v5Create a router and your first route
Create a router with chi.NewRouter(), attach a middleware with r.Use, and register a handler for a method and path. Then pass the router to http.ListenAndServe, because chi's router is a standard http.Handler.
The example below serves a welcome message on port 3000 and logs each request with the Logger middleware.
package main
import (
"net/http"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
)
func main() {
r := chi.NewRouter()
r.Use(middleware.Logger)
r.Get("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("welcome"))
})
http.ListenAndServe(":3000", r)
}Define REST routes with methods and URL parameters
chi provides a method for each HTTP verb, such as Get, Post, Put and Delete. Each routing method takes a URL pattern and a handler. Patterns support named parameters like /users/{userID} and wildcards like /admin/*.
You can also use regular expressions in a parameter, for example {articleSlug:[a-z-]+}. Inside a handler, read a parameter with chi.URLParam.
- Get, Post, Put and Delete map to the matching HTTP methods.
- Named parameters use braces: {articleID}.
- Wildcards use an asterisk at the end of a pattern: /admin/*.
- Regular expression parameters use the form {name:regexp}.
r.Route("/articles", func(r chi.Router) {
r.Get("/", listArticles) // GET /articles
r.Post("/", createArticle) // POST /articles
r.Get("/search", searchArticles) // GET /articles/search
r.Route("/{articleID}", func(r chi.Router) {
r.Get("/", getArticle) // GET /articles/123
r.Put("/", updateArticle) // PUT /articles/123
r.Delete("/", deleteArticle) // DELETE /articles/123
})
})Add middleware, route groups and sub-routers
r.Use adds middleware to the whole router. r.With adds middleware to a single endpoint. r.Group creates an inline router with its own middleware stack. r.Route mounts a sub-router along a pattern, and r.Mount attaches another http.Handler, such as a separate router, under a path.
The optional middleware package includes items such as Logger, RequestID, Recoverer and Timeout. The README's full example uses a base stack of these with a 60 second timeout.
- Use: applies to every route on the router.
- With: applies to one endpoint, for example r.With(paginate).Get("/", listArticles).
- Group: creates a new inline router with a fresh middleware stack.
- Route and Mount: attach sub-routers or handlers along a path.
r := chi.NewRouter()
r.Use(middleware.RequestID)
r.Use(middleware.Logger)
r.Use(middleware.Recoverer)
r.Use(middleware.Timeout(60 * time.Second))
// Mount a separate router under /admin
r.Mount("/admin", adminRouter())Read request data and load resources in middleware
A common pattern is a middleware that reads a URL parameter, loads the matching resource, and stores it in the request context with context.WithValue. The handler then reads the value back from r.Context(). The README example returns a 404 when the lookup fails and a 422 when the value is missing from the context.
Context keys in the README example are plain strings. Check the chi examples in the repository before you copy this pattern into production code.
func ArticleCtx(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
articleID := chi.URLParam(r, "articleID")
article, err := dbGetArticle(articleID)
if err != nil {
http.Error(w, http.StatusText(404), 404)
return
}
ctx := context.WithValue(r.Context(), "article", article)
next.ServeHTTP(w, r.WithContext(ctx))
})
}Generate route documentation
The docgen package, listed as an optional subpackage, generates routing documentation from your source to JSON or Markdown. The chi repository includes example output files called routes.json and routes.md in its REST example.
What people use it for
- A REST API for articles with list, create, read, update and delete endpoints under /articles/{articleID}.
- An admin area mounted under /admin, protected by its own middleware that checks permissions.
- A public API with a shared middleware stack for request IDs, logging, panic recovery and request timeouts.
- Generated route documentation in JSON or Markdown from the router source using the docgen package.
Frequently asked questions
How do I install chi?
Run go get -u github.com/go-chi/chi/v5 inside your Go module. The README gives this command for chi v5. Then import github.com/go-chi/chi/v5 in your code.
Is chi free to use?
chi is open source under the MIT licence. The README does not list any paid tier.
What do I need before using chi?
You need Go installed. The README does not specify which Go version is required, so check the project documentation for that. You should also understand Go handlers and context, since the README assumes this knowledge.
Is chi compatible with net/http?
Yes. The README states that chi is 100% compatible with net/http, so you can use other http or middleware packages that also work with net/http.
How does chi compare to gorilla/mux, httprouter, gin and echo?
This source does not include a comparison or benchmark results, so it cannot say which is faster. chi's README describes itself as a small, net/http-based router focused on composable REST APIs. Gin and Echo are broader frameworks, while gorilla/mux and httprouter are other routers you can evaluate yourself.
Does chi include templates, an ORM or authentication?
No. The README says chi covers routing and relies on separate packages for other needs. Its optional subpackages are middleware, render and docgen.
New agent skills, repos and AI tools — every week
The best new skills and open-source projects, the fastest-growing repos, and one free prompt. Five minutes to read. Unsubscribe anytime.
Our verdict
chi suits Go developers who are building REST APIs and want routing that stays close to the standard net/http package. Pick something else if you want a full framework with templates, an ORM and built-in authentication, or if you are new to Go.
Install options & downloads