Parameterized Routes
Use route parameters, prepared pattern matchers, and custom regex constraints to validate URL segments before requests reach handlers.
Parameterized routes allow dynamic values to be captured from the URL path.
r.GET("/users/{id}", func(w http.ResponseWriter, req *http.Request, ctx *router.Context) {
id := ctx.Param("id")
w.Write([]byte(id))
})Request:
/users/42Captured parameter:
id = 42Route parameters are accessed through ctx.Param.
id := ctx.Param("id")Why Use Route Patterns
Route patterns allow the router to validate URL segments before the request reaches the handler.
This is useful when a route expects a specific value format, such as:
- numeric IDs
- UUIDs
- slugs
- dates
- safe filenames
- hexadecimal tokens
- base64 strings
For example, if a route expects a UUID, the router can reject invalid requests before the handler runs.
This keeps handlers cleaner and avoids unnecessary application logic for requests that do not match the expected URL shape.
Basic Parameters
Use {name} to capture any single path segment.
r.GET("/users/{id}", handler)
r.GET("/posts/{slug}", handler)Examples:
| Route | Request | Captured Value |
|---|---|---|
/users/{id} | /users/42 | id = 42 |
/posts/{slug} | /posts/hello-world | slug = hello-world |
Prepared Pattern Matchers
Prepared pattern matchers are named, built-in validators.
They are faster and easier to read than custom regular expressions because they are implemented as direct Go functions.
Syntax:
{name:matcher}Example:
r.GET("/users/{id:isDigits}", func(w http.ResponseWriter, req *http.Request, ctx *router.Context) {
id := ctx.Param("id")
w.Write([]byte(id))
})This route matches:
/users/123but does not match:
/users/abcSupported Pattern Matchers
| Matcher | Pattern | Description | Example |
|---|---|---|---|
isLowerAlpha | [a-z]+ | Lowercase letters only | abc |
isUpperAlpha | [A-Z]+ | Uppercase letters only | ABC |
isAlpha | [a-zA-Z]+ | Letters only | Test |
isDigits | [0-9]+, \d+ | Digits only | 123456 |
isAlnum | [a-zA-Z0-9]+ | Letters and digits | user42 |
isWord | \w+ | Letters, digits, underscore | hello_world |
isSlugSafe | [\w\-]+ | Word characters and hyphen | post-title |
isSlug | [a-z0-9\-]+ | Lowercase slug | my-article |
isHex | [a-fA-F0-9]+ | Hexadecimal string | 3fA9 |
isUUID | UUID format | UUID value | 550e8400-e29b-41d4-a716-446655440000 |
isSafeText | [a-zA-Z0-9 _.-]+ | Safe text value | File name-1 |
isUpperAlnum | [A-Z0-9]+ | Uppercase letters and digits | ADMIN99 |
isBase64 | a-zA-Z0-9+/= | Base64-safe string | SGVsbG8= |
isDateYMD | \d{4}-\d{2}-\d{2} | Date in YYYY-MM-DD format | 2026-05-12 |
isSafePath | [a-zA-Z0-9/._-]+ | Safe path-like value | img/uploads/logo.png |
any | .* | Always matches | any value |
Regex Parameters
For more specific validation, routes can use custom regular expressions.
Syntax:
{name:regex}Examples:
| Route | Description |
|---|---|
/user/{id:(\\d+)} | Only numeric IDs |
/post/{slug:([a-zA-Z0-9\-_]+)} | Slug-friendly values with hyphens and underscores |
/file/{filename:([\\S]+)}/{token:([0-9]+)} | Multiple validated parameters in one route |
Example:
r.GET("/user/{id:(\\d+)}", func(w http.ResponseWriter, req *http.Request, ctx *router.Context) {
id := ctx.Param("id")
w.Write([]byte(id))
})Named Matcher vs Regex
These two routes behave similarly:
r.GET("/user/{id:isDigits}", handler)r.GET("/user/{id:(\\d+)}", handler)The named matcher is preferred when available because it is:
- easier to read
- easier to maintain
- faster than full regular expression matching
- less error-prone
Use custom regex only when the built-in matcher is not expressive enough.
Multiple Parameters
Routes can contain multiple parameters.
r.GET("/file/{filename:isSafeText}/{token:isDigits}", func(w http.ResponseWriter, req *http.Request, ctx *router.Context) {
filename := ctx.Param("filename")
token := ctx.Param("token")
w.Write([]byte(filename + ":" + token))
})Example request:
/file/report.pdf/12345Captured values:
filename = report.pdf
token = 12345How Matching Works
The router checks parameter constraints before executing the handler.
If the URL does not match the expected pattern, the handler is not called.
This allows route validation to happen at the routing layer instead of inside every handler.
The matching priority is:
- plain parameters, such as
{id} - prepared pattern matchers, such as
{id:isDigits} - custom regex parameters, such as
{id:(\\d+)}
Prepared matchers are optimized for common cases and should be preferred when possible.
When to Use Regex
Use regex parameters when you need validation rules that are not covered by the prepared matchers.
Example:
r.GET("/match/{slug:([a-z]+_[0-9]{2})}", handler)This is useful for advanced URL formats.
For common values such as IDs, UUIDs, slugs, dates, and tokens, prefer prepared pattern matchers.
Notes
Route patterns are not a replacement for business validation.
They are designed to reject invalid URL shapes early, before the request enters the handler.
Handlers should still validate permissions, ownership, database state, request bodies, and application-specific rules.