# How to Use Route Groups and Nested Groups in Gin

> Master Gin route groups and nested groups to organize URLs, apply middleware to sections, and build hierarchical APIs efficiently. Streamline your web application development today.

- Repository: [Gin-Gonic/gin](https://github.com/gin-gonic/gin)
- Tags: how-to-guide
- Published: 2026-02-27

---

**Route groups in Gin let you organize URLs under common prefixes and attach middleware to specific logical sections, while nested groups automatically concatenate paths via `calculateAbsolutePath` and inherit parent middleware chains for hierarchical API structures.**

Organizing HTTP endpoints in a web framework requires clean URL prefixes and reusable middleware stacks. In the `gin-gonic/gin` repository, the **RouterGroup** type provides the foundation for both flat and hierarchical routing structures. Understanding how to use route groups and nested groups in Gin allows you to build modular APIs where authentication, logging, and versioning are applied precisely where needed.

## Understanding RouterGroup Core Concepts

The `RouterGroup` struct defined in [`routergroup.go`](https://github.com/gin-gonic/gin/blob/main/routergroup.go) manages collections of routes that share a common **base path** and handler chain. When you invoke the `Group` method, Gin instantiates a new group whose base path is the parent’s path joined with the supplied `relativePath` (source lines 70-76 in [`routergroup.go`](https://github.com/gin-gonic/gin/blob/main/routergroup.go)). This concatenation logic resides in `calculateAbsolutePath`, which ensures clean joining— for example, merging `/v1` with `/admin` produces `/v1/admin` without double slashes (source lines 50-52 in [`routergroup.go`](https://github.com/gin-gonic/gin/blob/main/routergroup.go)).

Each group maintains its own slice of middleware handlers. Calling `Use` on a group appends middleware to that slice, meaning those handlers execute only for routes registered on that group and its descendants (source lines 64-68 in [`routergroup.go`](https://github.com/gin-gonic/gin/blob/main/routergroup.go)). When you register a route using methods like `GET` or `POST`, the internal `handle` function resolves the absolute URL by combining the group’s base path with the route’s relative path before registering it with the underlying HTTP router (source lines 86-90 in [`routergroup.go`](https://github.com/gin-gonic/gin/blob/main/routergroup.go)).

## Creating Basic Route Groups

Start by calling `Group` on an existing `RouterGroup`—including the root `Engine` created by `gin.Default()` or `gin.New()`. This returns a new group that inherits the parent’s middleware but can accept its own via the `Use` method.

```go
router := gin.Default()

// Create a group with prefix /api
api := router.Group("/api")
api.Use(AuthMiddleware)

// These resolve to /api/users and /api/users
api.GET("/users", listUsers)
api.POST("/users", createUser)

```

In this example, `AuthMiddleware` executes only for routes defined on the `api` group. The root engine and other groups remain unaffected.

## Implementing Nested Route Groups

Nested groups enable versioning and administrative sub-sections without repeating path prefixes. When you call `Group` on an existing group rather than the engine, Gin invokes `calculateAbsolutePath` to build the child’s base path by appending the new segment to the parent’s (source lines 50-52 in [`routergroup.go`](https://github.com/gin-gonic/gin/blob/main/routergroup.go)). The child also inherits the parent’s middleware chain, allowing you to stack additional handlers for deeper levels.

```go
router := gin.Default()

v1 := router.Group("/v1")
v1.Use(Logger())

// Nested group: base path becomes /v1/admin
admin := v1.Group("/admin")
admin.Use(AdminOnly())

admin.GET("/stats", adminStats)       // Resolves to GET /v1/admin/stats
admin.POST("/users", adminCreateUser) // Resolves to POST /v1/admin/users

```

Requests to `/v1/admin/stats` execute `Logger()` (from the parent), then `AdminOnly()` (from the child), then `adminStats`. This composable architecture keeps your security layers DRY while isolating administrative logic.

## Advanced Route Registration Methods

Groups support flexible HTTP method registration beyond standard verbs. Use `Any` to respond to all HTTP methods—this loops over Gin’s internal list of all methods and registers the handler for each (source lines 45-48 in [`routergroup.go`](https://github.com/gin-gonic/gin/blob/main/routergroup.go)). Use `Match` to restrict specific verbs (source lines 55-60 in [`routergroup.go`](https://github.com/gin-gonic/gin/blob/main/routergroup.go)).

```go
api := router.Group("/api")

// Responds to GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS
api.Any("/ping", pingHandler)

// Only responds to GET or POST at /api/upload
api.Match([]string{http.MethodGet, http.MethodPost}, "/upload", uploadHandler)

```

## Inspecting Group Paths with BasePath

For debugging or dynamic route generation, call `BasePath()` to retrieve the fully resolved prefix of any group. This method returns the `basePath` field computed during group creation (source lines 80-84 in [`routergroup.go`](https://github.com/gin-gonic/gin/blob/main/routergroup.go)).

```go
v1 := router.Group("/v1")
admin := v1.Group("/admin")
fmt.Println(admin.BasePath()) // Output: /v1/admin

```

This is particularly useful when splitting route definitions across multiple files and needing to verify the final URL structure at runtime.

## Summary

- **RouterGroup** is the core type in [`routergroup.go`](https://github.com/gin-gonic/gin/blob/main/routergroup.go) for organizing routes with common prefixes and middleware stacks in Gin.
- The `Group` method creates new groups; nested groups automatically concatenate paths via `calculateAbsolutePath` (lines 50-52) to build hierarchical URLs like `/v1/admin`.
- Middleware added via `Use` applies to the group and all its children, enabling composable security and logging layers that execute in parent-to-child order.
- Flexible registration methods `Any` and `Match` allow a single group to handle multiple HTTP verbs with precise control.
- The `BasePath()` method (lines 80-84) exposes the resolved URL prefix for runtime introspection.

## Frequently Asked Questions

### How do route groups handle middleware inheritance in Gin?

When you create a nested group, the child inherits the parent’s handler chain because Gin copies the parent’s middleware slice into the child during instantiation. When `Use` is called on the child, it appends new handlers to this inherited slice (source lines 64-68 in [`routergroup.go`](https://github.com/gin-gonic/gin/blob/main/routergroup.go)). Consequently, parent middleware executes first, followed by child-specific middleware, creating a natural cascading execution order for authentication, logging, and authorization.

### What is the difference between `gin.Default()` and `gin.New()` when working with groups?

Both functions return an `Engine` instance that embeds a `RouterGroup`, but `gin.Default()` automatically attaches the `Logger` and `Recovery` middleware to the root group defined in [`gin.go`](https://github.com/gin-gonic/gin/blob/main/gin.go). When you call `Group` on either engine, the resulting child group behavior is identical; the only difference lies in the root middleware stack present before you define your own groups.

### Can I register routes directly on the root engine without creating a group?

Yes. Because `Engine` embeds `RouterGroup`, methods like `GET`, `POST`, and `Group` are available directly on the engine instance. This is functionally equivalent to creating a group with an empty base path, as the root engine initializes with `basePath` set to an empty string (source lines 70-76 in [`routergroup.go`](https://github.com/gin-gonic/gin/blob/main/routergroup.go)). Routes registered directly on the engine have no URL prefix unless you specify one in the path argument.

### How does Gin prevent duplicate slashes when nesting groups with trailing slashes?

The `calculateAbsolutePath` function in [`routergroup.go`](https://github.com/gin-gonic/gin/blob/main/routergroup.go) normalizes path concatenation by cleaning the resulting string, ensuring that joining `/v1/` with `/admin` produces `/v1/admin` rather than `/v1//admin` (source lines 50-52). To ensure consistent behavior across all Gin versions, always include a leading slash in your relative path arguments when calling `Group`.