Что такое 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", "")
Что делает: Ограничивает маршрут по имени хоста. Полезно для обработки запросов от разных доменов одним сервером.
Параметры: 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