GinJuniorCoding
Как работают группы маршрутов в Gin и каковы их сценарии использования?
Группы маршрутов в Gin создаются через r.Group("/prefix", middleware...) и объединяют маршруты с общим URL-префиксом и middleware. Основные сценарии: версионирование API (/api/v1, /api/v2) и разделение публичных и приватных эндпоинтов.
Группы маршрутов в Gin
Группа маршрутов (RouterGroup) позволяет объединять маршруты с общим префиксом пути и/или общим набором middleware. Это ключевой инструмент для структурирования API.
Базовый синтаксис
package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
// Группа /api/v1
v1 := r.Group("/api/v1")
{
v1.GET("/users", listUsers) // GET /api/v1/users
v1.POST("/users", createUser) // POST /api/v1/users
v1.GET("/users/:id", getUser) // GET /api/v1/users/:id
v1.PUT("/users/:id", updateUser) // PUT /api/v1/users/:id
v1.DELETE("/users/:id", deleteUser) // DELETE /api/v1/users/:id
}
// Группа /api/v2
v2 := r.Group("/api/v2")
{
v2.GET("/users", listUsersV2)
}
r.Run(":8080")
}
Middleware на уровне группы
Middleware, переданный в Group(), применяется только к маршрутам этой группы:
func AuthRequired() gin.HandlerFunc {
return func(c *gin.Context) {
token := c.GetHeader("Authorization")
if token == "" {
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{
"error": "unauthorized",
})
return
}
c.Next()
}
}
func main() {
r := gin.New()
r.Use(gin.Recovery())
// Публичные маршруты — без аутентификации
public := r.Group("/")
{
public.POST("/login", loginHandler)
public.GET("/health", healthHandler)
}
// Приватные маршруты — требуют токен
private := r.Group("/api", AuthRequired())
{
private.GET("/profile", profileHandler)
private.POST("/orders", createOrderHandler)
}
r.Run(":8080")
}
Вложенные группы
Группы можно вкладывать друг в друга для более детальной структуры:
admin := r.Group("/admin", AuthRequired(), AdminOnly())
{
users := admin.Group("/users")
{
users.GET("/", listAdminUsers) // GET /admin/users/
users.DELETE("/:id", deleteUser) // DELETE /admin/users/:id
}
posts := admin.Group("/posts")
{
posts.GET("/", listAdminPosts) // GET /admin/posts/
posts.POST("/", createPost) // POST /admin/posts/
}
}
Группы для версионирования API
func RegisterV1Routes(rg *gin.RouterGroup) {
rg.GET("/products", listProductsV1)
rg.GET("/products/:id", getProductV1)
}
func RegisterV2Routes(rg *gin.RouterGroup) {
rg.GET("/products", listProductsV2) // другая пагинация/формат
rg.GET("/products/:id", getProductV2)
}
func main() {
r := gin.Default()
RegisterV1Routes(r.Group("/api/v1"))
RegisterV2Routes(r.Group("/api/v2"))
r.Run(":8080")
}
Подводные камни
- Фигурные скобки — только для читаемости. Синтаксис
v1 := r.Group(...) { ... }— это обычный блок Go, не обязательный. Маршруты можно регистрировать без блока. - Middleware группы не наследуется автоматически вложенными группами. При вызове
admin.Group("/users")middleware AdminOnly() НЕ передаётся в подгруппу — нужно явно передавать или добавлять черезsubgroup.Use(). - Нельзя добавить middleware к группе после регистрации маршрутов. Вызов
group.Use(mw)послеgroup.GET(...)не применит middleware к уже зарегистрированным маршрутам. - Конфликты префиксов. Маршруты
/apiв одной группе и/api/v1в другой не конфликтуют, но/api/:versionи/api/v1вызовут панику при регистрации. - Порядок middleware в глобальном Use() vs группового. Глобальные middleware (
r.Use()) выполняются до групповых. Учитывайте это при проектировании цепочки аутентификации. - Пустой префикс группы.
r.Group("")создаёт группу без добавления к пути — используется исключительно для применения middleware без изменения структуры URL.
Common mistakes
- Давать ответ про groups маршрутов в Gin только на уровне определения, не показывая поведение в реальном приложении.
- Игнорировать границы ответственности вокруг темы «groups маршрутов в Gin»: кто отменяет работу, кто владеет ресурсом и где формируется ответ клиенту.
- Не связывать groups маршрутов в Gin с observability, тестированием или безопасностью, когда это влияет на продакшен-поведение.
What the interviewer is testing
- Точно объясняет, что именно делает groups маршрутов в Gin и где это используется в Go-коде.
- Связывает groups маршрутов в Gin с корректным lifecycle запроса, отменой, конкурентностью или конфигурацией сервера там, где это уместно.
- Не изобретает API и опирается на реальные контракты официальной документации.