Gorilla Mux для Go: полное руководство с примерами

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Что такое Gorilla Mux и зачем он нужен?

Gorilla Mux (часто называют просто "mux" от "multiplexer") — это мощный и популярный HTTP роутер (маршрутизатор) для языка программирования Go. Он является частью экосистемы Gorilla Web Toolkit, которая предоставляет множество полезных компонентов для веб-разработки.

Зачем нужен отдельный роутер, если в стандартной библиотеке Go уже есть net/http? Стандартный http.ServeMux отлично подходит для простых проектов, но имеет ряд ограничений:

  • Нет поддержки динамических сегментов пути (например, /users/{id}).
  • Нет поддержки методов HTTP (GET, POST, PUT, DELETE) — нужно проверять вручную.
  • Нет поддержки регулярных выражений в маршрутах.
  • Нет встроенных middleware (промежуточного ПО).

Gorilla Mux решает все эти проблемы. Он позволяет:

  • Определять сложные маршруты с переменными частями.
  • Ограничивать маршруты по HTTP-методам, хостам, заголовкам и query-параметрам.
  • Использовать суброутеры (subrouters) для группировки маршрутов.
  • Легко интегрироваться с middleware.
  • Строить RESTful API с чистыми и понятными URL.

Библиотека Gorilla Mux — это стандарт де-факто для построения HTTP-серверов в Go. Она используется в тысячах проектов, от небольших микросервисов до крупных коммерческих приложений.

Установка

Установка Gorilla Mux в Go-проект осуществляется через менеджер пакетов go get. Откройте терминал в корне вашего проекта и выполните команду:

go get -u github.com/gorilla/mux

Эта команда скачает библиотеку и добавит её в ваш файл go.mod. После этого вы можете импортировать её в своём коде:

import "github.com/gorilla/mux"

Если вы используете Go Modules (а это стандарт для Go 1.16+), то библиотека будет автоматически добавлена в ваш go.mod и go.sum файлы. Всё готово к работе!

Быстрый старт: простой HTTP сервер с Gorilla Mux

Давайте создадим минимальный веб-сервер, который будет обрабатывать GET-запросы на корневой путь и возвращать приветствие.

package main

import (
    "fmt"
    "log"
    "net/http"

    "github.com/gorilla/mux"
)

func main() {
    // Создаём новый роутер
    r := mux.NewRouter()

    // Определяем маршрут: GET /
    r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Привет, мир! Это Gorilla Mux!")
    })

    // Запускаем сервер на порту 8080
    log.Println("Сервер запущен на http://localhost:8080")
    log.Fatal(http.ListenAndServe(":8080", r))
}

Запустите этот код (go run main.go) и откройте в браузере http://localhost:8080. Вы увидите сообщение "Привет, мир! Это Gorilla Mux!".

Обратите внимание: мы передаём наш роутер r в http.ListenAndServe. Это возможно, потому что mux.Router реализует интерфейс http.Handler.

Основные методы и функции Gorilla Mux

Рассмотрим ключевые методы библиотеки. Каждый метод будет сопровождаться описанием, параметрами и рабочим примером.

1. mux.NewRouter()

Что делает: Создаёт новый экземпляр роутера. Это отправная точка для всех маршрутов.

Параметры: Нет.

Возвращает: Указатель на mux.Router.

r := mux.NewRouter()
// Теперь r готов к определению маршрутов

2. r.HandleFunc(path, handler)

Что делает: Регистрирует функцию-обработчик для заданного пути. Это основной способ определения маршрутов.

Параметры:

  • path (string): URL-шаблон (например, "/users", "/users/{id}").
  • handler (func(http.ResponseWriter, *http.Request)): Функция, которая будет вызвана при совпадении маршрута.

Возвращает: *mux.Route — объект маршрута, который можно дальше настраивать (например, ограничивать по методам).

r := mux.NewRouter()
r.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("Hello!"))
})

3. r.Handle(path, handler)

Что делает: Аналогичен HandleFunc, но принимает объект, реализующий интерфейс http.Handler (т.е. имеющий метод ServeHTTP). Полезно, когда у вас есть готовый handler.

Параметры:

  • path (string): URL-шаблон.
  • handler (http.Handler): Объект-обработчик.
type myHandler struct{}

func (h *myHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("Hello from handler!"))
}

r := mux.NewRouter()
r.Handle("/handler", &myHandler{})

4. route.Methods(methods ...string)

Что делает: Ограничивает маршрут только указанными HTTP-методами. Это критически важно для построения REST API.

Параметры: Один или несколько строковых аргументов — названия HTTP методов (GET, POST, PUT, DELETE, PATCH, OPTIONS и т.д.).

Возвращает: *mux.Route для цепочки вызовов.

r := mux.NewRouter()
r.HandleFunc("/api/users", createUser).Methods("POST")
r.HandleFunc("/api/users/{id}", getUser).Methods("GET")
r.HandleFunc("/api/users/{id}", updateUser).Methods("PUT")
r.HandleFunc("/api/users/{id}", deleteUser).Methods("DELETE")

5. mux.Vars(r)

Что делает: Извлекает переменные пути (динамические сегменты) из HTTP-запроса. Это ключевая функция для работы с динамическими URL.

Параметры: r (*http.Request) — текущий HTTP-запрос.

Возвращает: map[string]string — карту, где ключи — имена переменных, а значения — их значения из URL.

r := mux.NewRouter()
r.HandleFunc("/users/{id}", func(w http.ResponseWriter, r *http.Request) {
    vars := mux.Vars(r)
    userID := vars["id"]
    w.Write([]byte("User ID: " + userID))
})

Если запрос приходит на /users/42, то userID будет равен "42".

6. route.Queries(key, value, ...)

Что делает: Ограничивает маршрут по наличию и значению query-параметров в URL. Позволяет создавать очень точные маршруты.

Параметры: Чётное количество строк: пары "ключ-значение". Если значение — пустая строка, то проверяется только наличие параметра.

Возвращает: *mux.Route.

r := mux.NewRouter()
// Сработает только если есть ?category=books
r.HandleFunc("/search", searchHandler).Queries("category", "books")
// Сработает, если есть параметр 'q' (любое значение)
r.HandleFunc("/search", searchAllHandler).Queries("q", "")
route.Host(hostname)

Что делает: Ограничивает маршрут по имени хоста. Полезно для обработки запросов от разных доменов одним сервером.

Параметры: hostname (string) — имя хоста (например, "api.example.com").

Возвращает: *mux.Route.

r := mux.NewRouter()
r.HandleFunc("/", apiHandler).Host("api.example.com")
r.HandleFunc("/", webHandler).Host("www.example.com")

8. route.Schemes(schemes ...string)

Что делает: Ограничивает маршрут по протоколу (http или https).

Параметры: Один или несколько строк — "http" и/или "https".

Возвращает: *mux.Route.

r := mux.NewRouter()
r.HandleFunc("/secure", secureHandler).Schemes("https")
r.HandleFunc("/", generalHandler).Schemes("http", "https")

9. route.Headers(key, value, ...)

Что делает: Ограничивает маршрут по наличию и значению HTTP-заголовков. Часто используется для проверки Content-Type или Authorization.

Параметры: Чётное количество строк: пары "ключ-значение".

Возвращает: *mux.Route.

r := mux.NewRouter()
// Принимаем только JSON
r.HandleFunc("/api/data", jsonHandler).Headers("Content-Type", "application/json")
// Принимаем только XML
r.HandleFunc("/api/data", xmlHandler).Headers("Content-Type", "application/xml")

10. route.Subrouter()

Что делает: Создаёт вложенный (дочерний) роутер, который наследует префикс пути от родительского маршрута. Это мощный инструмент для организации кода.

Параметры: Нет (вызывается на объекте Route).

Возвращает: *mux.Router — новый суброутер.

r := mux.NewRouter()
// Создаём суброутер для /api/v1
api := r.PathPrefix("/api/v1").Subrouter()
// Все маршруты api будут иметь префикс /api/v1
api.HandleFunc("/users", getUsers).Methods("GET")
api.HandleFunc("/users/{id}", getUser).Methods("GET")
// Эквивалентно r.HandleFunc("/api/v1/users", ...)

11. route.Name(name) и route.URL(name, pairs ...string)

Что делает: Позволяет дать имя маршруту и затем генерировать URL по этому имени. Это избавляет от "зашитых" URL в коде.

Параметры:

  • Name: name (string) — имя маршрута.
  • URL: name (string) — имя маршрута, pairs — пары "ключ-значение" для переменных пути.
r := mux.NewRouter()
r.HandleFunc("/users/{id}", getUser).Methods("GET").Name("getUser")

// Где-то в другом месте:
url, _ := r.Get("getUser").URL("id", "123                    

Рекомендаций