FiberSeniorTechnical

В чём различия между Fiber v2 и его предшественником по API и функциональности?

Fiber v2 перешёл на модульную архитектуру с отдельными пакетами middleware, изменил сигнатуры обработчиков на возврат error, добавил Ctx.BodyParser, Generic-роуты и улучшил производительность за счёт fasthttp обновлений.

Fiber v2 vs v1: ключевые отличия

Fiber v2 — это не инкрементальное обновление, а переработка API с нарушением обратной совместимости. Изменения охватывают сигнатуры, middleware-экосистему, конфигурацию и обработку ошибок.

1. Сигнатура обработчика

Самое заметное изменение: handlers теперь возвращают error.

// v1
app.Get("/", func(c *fiber.Ctx) {
	c.Send("hello")
})

// v2
app.Get("/", func(c *fiber.Ctx) error {
	return c.SendString("hello")
})

Это позволяет централизованно обрабатывать ошибки через app.Use(ErrorHandler) и стандартный паттерн Go.

2. Централизованная обработка ошибок

app := fiber.New(fiber.Config{
	ErrorHandler: func(c *fiber.Ctx, err error) error {
		code := fiber.StatusInternalServerError
		var e *fiber.Error
		if errors.As(err, &e) {
			code = e.Code
		}
		return c.Status(code).JSON(fiber.Map{"error": err.Error()})
	},
})

В v1 ошибки нужно было обрабатывать внутри каждого обработчика вручную.

3. Middleware вынесены в отдельные репозитории

В v1 все middleware были частью основного пакета. В v2 каждый middleware живёт в github.com/gofiber/fiber/v2/middleware/:

import (
	"github.com/gofiber/fiber/v2/middleware/cors"
	"github.com/gofiber/fiber/v2/middleware/logger"
	"github.com/gofiber/fiber/v2/middleware/recover"
	"github.com/gofiber/fiber/v2/middleware/limiter"
)

app.Use(recover.New())
app.Use(logger.New(logger.Config{
	Format: "${method} ${path} ${status} ${latency}\n",
}))
app.Use(cors.New(cors.Config{
	AllowOrigins: "https://example.com",
	AllowHeaders: "Origin, Content-Type, Authorization",
}))
app.Use(limiter.New(limiter.Config{
	Max:        100,
	Expiration: 1 * time.Minute,
}))

4. BodyParser и валидация

type LoginRequest struct {
	Email    string `json:"email" validate:"required,email"`
	Password string `json:"password" validate:"required,min=8"`
}

app.Post("/login", func(c *fiber.Ctx) error {
	var req LoginRequest
	if err := c.BodyParser(&req); err != nil {
		return fiber.NewError(fiber.StatusBadRequest, "invalid body")
	}
	// ...
	return c.JSON(fiber.Map{"token": "..."})
})

В v1 парсинг тела требовал отдельного вызова c.JSON() только для отправки; входящий JSON парсился через c.BodyParser(), но API был менее стабильным.

5. Prefork и конфигурация приложения

app := fiber.New(fiber.Config{
	Prefork:               true,     // SO_REUSEPORT, несколько процессов
	CaseSensitive:         true,     // /User != /user
	StrictRouting:         true,     // /foo/ != /foo
	ServerHeader:          "Fiber",
	BodyLimit:             4 * 1024 * 1024, // 4 MB
	ReadTimeout:           5 * time.Second,
	WriteTimeout:          10 * time.Second,
	DisableStartupMessage: false,
})

6. Новые методы Ctx

  • c.Bind() — привязка query/form/json из одного вызова (v2.50+)
  • c.GetReqHeaders() — все заголовки как map
  • c.Protocol() — http или https с учётом X-Forwarded-Proto
  • c.IsFromLocal() — проверка локального IP
  • c.SaveFile() / c.SaveFileToStorage() — сохранение multipart

7. Маршрутизация

// Группы с middleware (v2 API стабилизирован)
api := app.Group("/api", authMiddleware)
v1 := api.Group("/v1")
v1.Get("/users", getUsers)
v1.Post("/users", createUser)

// Named параметры + regex
app.Get("/user/:id<int>", getUserById)  // только числовые id
app.Get("/files/*",       serveFiles)   // wildcard

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

  • Миграция сигнатур: если вы копируете handler из v1-проекта, компилятор не сразу укажет на отсутствие error в возврате — тип func(*fiber.Ctx) и func(*fiber.Ctx) error несовместимы.
  • c.Body() возвращает слайс байт: в v2 тело запроса доступно только до конца хендлера — после него буфер освобождается fasthttp. Если нужно хранить тело дольше, скопируйте его: body := make([]byte, len(c.Body())); copy(body, c.Body()).
  • Prefork на Windows: Prefork: true не работает на Windows (нет SO_REUSEPORT). Приложение упадёт с ошибкой при старте.
  • c.Locals() и горутины: передавать *fiber.Ctx в горутины опасно — контекст переиспользуется пулом. Копируйте нужные данные в переменные до запуска горутины.
  • Изменение импортного пути: v2 использует github.com/gofiber/fiber/v2, а не github.com/gofiber/fiber. Забытый старый импорт тихо компилируется с другим API.
  • Middleware порядок: recover.New() нужно регистрировать первым, до всех остальных middleware — иначе паника в cors или logger не будет поймана.
  • fiber.Error vs обычный error: fiber.NewError(404, "not found") автоматически устанавливает HTTP-статус в ErrorHandler; обычный errors.New() даст 500.

Common mistakes

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

What the interviewer is testing

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

Sources

Related topics