Новое:Talanto осенью: поиск с цифрами, вакансия по шагам и каталог компаний

+1 472новые вакансии за сутки·93 728вакансий открыто сейчас·Новое:Talanto осенью: поиск с цифрами, вакансия по шагам и каталог компаний

Новые вакансии в TelegramРаботодателям
Talanto
Вакансии
Компании7 267
РезюмеAIПодготовкаСтатьи
BoostТарифыBoost
Войти

Не нашли подходящее?

Пусть нужная вакансия найдёт вас сама.

  1. Подборка в TelegramНовые вакансии по вашему фильтру — сразу в бота.Подключить
  2. Мэтчи по резюмеЗагрузите резюме — покажем, где вы подходите лучше всего.Загрузить
  3. Сохранить фильтрНастройте поиск один раз и возвращайтесь к новым вакансиям.Настроить
Что нового на TalantoTalanto осенью: поиск с цифрами, вакансия по шагам и каталог компаний

Для работодателей

Опубликуйте вакансию — отклики придут в ваш кабинет.

  1. Вакансиябесплатно
  2. Откликиконтакты бесплатно
  3. Наймэтапы и интервью

40 компаний публикуют вакансии напрямую · 4 402 кандидата открыты к предложениям

Разместить вакансию

Популярные направления

Все подборки
  • Python17 124
  • Облачные технологии14 081
  • QA вакансии3 459
  • Backend вакансии2 116
  • Инженер данных1 804
  • Продакт-менеджер1 264

Разработка

  • Android1 866
  • iOS1 701
  • Fullstack вакансии988
  • AI вакансии952
  • Frontend вакансии744
  • Mobile вакансии44

По стеку

  • Go8 662
  • Java6 548
  • Node.js2 019
  • .NET1 722
  • Kotlin1 619
  • Rust1 454
  • C#711
  • PHP683
  • C++571

DevOps и инфраструктура

  • Kubernetes7 766
  • DevOps вакансии6 053
  • Linux-инфраструктура5 491
  • Terraform / IaC4 262
  • CI/CD3 242
  • Мониторинг и Observability1 787
  • SRE567
  • Кибербезопасность453

Аналитика и данные

  • Data Scientist1 140
  • Бизнес-аналитик927
  • Аналитик данных854
  • Системный аналитик153

Другие направления

  • Проджект-менеджер615
  • UI/UX дизайн146
  • Ручное тестирование14

По регионам

  • Вакансии в США44 297
  • Вакансии в Европе23 854
  • Вакансии в Канаде4 476
  • Работа в России3 921

По формату

  • Удалённые вакансии75 046
  • Релокация в США44 297
  • Гибридная работа12 398
  • Офисная работа7 076

По уровню

  • Senior вакансии42 676
  • Middle вакансии20 894
  • Junior вакансии6 725

Сейчас нанимают

Все компании
  • Wise190 вакансий
  • Rakuten189 вакансий
  • ASML166 вакансий
  • Grab137 вакансий
  • Celonis39 вакансий
  • Spotify37 вакансий
  • Adyen28 вакансий
  • Infobip28 вакансий
  • Monzo20 вакансий
  • Darktrace16 вакансий

Вакансии из 344 источников: карьерные страницы компаний и джоб-борды.

КомпанииО насНовостиПубличная офертаУсловия использованияПолитика конфиденциальностиПоддержка
←К теме GinВсе вопросы
GinMiddleКодинг

Как создать и зарегистрировать собственный middleware в Gin?

В закладки
Сначала попробуйте ответить сами30 секунд
Сравнить с ответом ↓

Middleware в Gin — это func(*gin.Context) с вызовом c.Next() для передачи управления; регистрируется через r.Use() глобально, через Group().Use() для группы или прямо в маршруте.

Создание и регистрация middleware в Gin

Middleware в Gin — это функция типа gin.HandlerFunc, то есть func(*gin.Context). Ключевой момент: вызов c.Next() передаёт управление следующему handler-у в цепочке, а код после него выполняется на обратном ходу (как defer).

package middleware

import (
	"log/slog"
	"net/http"
	"time"

	"github.com/gin-gonic/gin"
)

// RequestLogger логирует метод, путь и время выполнения.
func RequestLogger() gin.HandlerFunc {
	return func(c *gin.Context) {
		start := time.Now()

		// Код ДО handler-а
		c.Next() // вызов следующего handler-а

		// Код ПОСЛЕ handler-а (обратный ход)
		duration := time.Since(start)
		slog.Info("request",
			"method", c.Request.Method,
			"path", c.Request.URL.Path,
			"status", c.Writer.Status(),
			"duration", duration,
		)
	}
}

// RequireAuth проверяет Bearer-токен.
func RequireAuth(secret string) gin.HandlerFunc {
	return func(c *gin.Context) {
		token := c.GetHeader("Authorization")
		if token != "Bearer "+secret {
			c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{
				"error": "unauthorized",
			})
			return // Abort уже остановил цепочку, но return обязателен
		}
		c.Next()
	}
}

Регистрация middleware бывает трёх уровней:

package main

import (
	"github.com/gin-gonic/gin"
	"myapp/middleware"
)

func main() {
	r := gin.New() // без встроенного logger/recovery

	// 1. Глобальный уровень — применяется ко всем маршрутам
	r.Use(middleware.RequestLogger())
	r.Use(gin.Recovery()) // встроенный recovery от паник

	// 2. Уровень группы — только для маршрутов внутри /api
	api := r.Group("/api", middleware.RequireAuth("secret-token"))
	{
		api.GET("/profile", profileHandler)
		api.GET("/settings", settingsHandler)
	}

	// 3. Уровень маршрута — только для конкретного endpoint
	r.DELETE("/admin/users/:id", middleware.RequireAuth("admin-secret"), deleteUserHandler)

	r.Run(":8080")
}

func profileHandler(c *gin.Context)  { c.JSON(200, gin.H{"user": "alice"}) }
func settingsHandler(c *gin.Context) { c.JSON(200, gin.H{"theme": "dark"}) }
func deleteUserHandler(c *gin.Context) {
	c.JSON(200, gin.H{"deleted": c.Param("id")})
}

Middleware может хранить данные в контексте для передачи вниз по цепочке:

func InjectUserID() gin.HandlerFunc {
	return func(c *gin.Context) {
		userID := extractUserIDFromToken(c.GetHeader("Authorization"))
		c.Set("userID", userID) // записываем в контекст
		c.Next()
	}
}

// В handler-е:
func profileHandler(c *gin.Context) {
	userID, _ := c.Get("userID")
	c.JSON(200, gin.H{"user_id": userID})
}

func extractUserIDFromToken(auth string) string {
	// упрощённая заглушка
	if len(auth) > 7 {
		return auth[7:]
	}
	return ""
}

Подводные камни

  • Если не вызвать c.Next() и не вызвать c.Abort(), последующие handler-ы в цепочке просто не выполнятся — молчаливый баг.
  • c.Abort() выставляет флаг, но не останавливает текущую функцию middleware — нужен явный return после вызова.
  • Порядок r.Use() имеет значение: middleware, зарегистрированный после r.Group(), не применяется к маршрутам этой группы, если группа создана до вызова Use.
  • c.Set/c.Get не потокобезопасны вне goroutine текущего запроса — не передавайте *gin.Context в фоновые горутины; копируйте нужные данные до запуска горутины.
  • Паника внутри middleware без gin.Recovery() уронит весь сервер; не используйте gin.New() без явного добавления Recovery.
  • Большое количество middleware, измеряющих время через time.Now(), складывается в заметный overhead на hot-path — профилируйте перед добавлением каждого нового слоя.
  • Middleware, написанный как замыкание с состоянием (например, счётчик), должен защищать shared state мьютексом или использовать sync/atomic.

Частые вопросы на собеседовании

  • В каких backend-проектах Gin (Go framework) является сильным выбором, а где лучше выбрать более простой или другой стек?
  • Что такое система валидации Gin и как использовать struct tags для валидации входных данных?
  • Как писать unit-тесты для Gin-обработчиков с помощью httptest?
  • Как реализовать middleware аутентификации (JWT) в Gin?

Типичные ошибки

  • Давать ответ про собственный middleware в Gin только на уровне определения, не показывая поведение в реальном приложении.
  • Игнорировать границы ответственности вокруг темы «собственный middleware в Gin»: кто отменяет работу, кто владеет ресурсом и где формируется ответ клиенту.
  • Не связывать собственный middleware в Gin с observability, тестированием или безопасностью, когда это влияет на продакшен-поведение.

Что проверяет интервьюер

  • Точно объясняет, что именно делает собственный middleware в Gin и где это используется в Go-коде.
  • Связывает собственный middleware в Gin с корректным lifecycle запроса, отменой, конкурентностью или конфигурацией сервера там, где это уместно.
  • Не изобретает API и опирается на реальные контракты официальной документации.

Как вы знаете этот вопрос?

Проверить себя по теме Gin →

Источники

  • https://gin-gonic.com/en/docs/middleware/custom-middleware/
  • https://gin-gonic.com/en/docs/middleware/
←Предыдущий вопросЧто такое `gin.Context` и какие ключевые операции он предоставляет?Следующий вопрос→Какой middleware включает `gin.Default()` по умолчанию?

Связанные темы

GinCodingGINMiddlewarerequest-lifecycle