Разработка бэкенда сайта на Go (Fiber)

Наша компания занимается разработкой, поддержкой и обслуживанием сайтов любой сложности. От простых одностраничных сайтов до масштабных кластерных систем построенных на микро сервисах. Опыт разработчиков подтвержден сертификатами от вендоров.
Разработка и обслуживание любых видов сайтов:
Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Предлагаемые услуги
Показано 1 из 1 услугВсе 2065 услуг
Разработка бэкенда сайта на Go (Fiber)
Средняя
от 1 недели до 3 месяцев
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1218
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    853
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1047
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    825
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    820

Разработка бэкенда сайта на Go (Fiber)

Fiber — Go-фреймворк, вдохновлённый Express.js. Если разработчик пришёл из Node.js, API покажется знакомым. Внутри — fasthttp вместо стандартного net/http, что даёт ~2x прирост в синтетических тестах на чистом HTTP. В реальных проектах с PostgreSQL и Redis разница меньше, но Fiber всё равно один из быстрейших Go-фреймворков.

Важный нюанс: fasthttp несовместим с net/http middleware. Это означает, что часть Go-экосистемы (например, стандартные OpenTelemetry middleware под net/http) не работает напрямую — нужны адаптеры или Fiber-специфичные пакеты.

Инициализация

package main

import (
    "log"
    "os"

    "github.com/gofiber/fiber/v2"
    "github.com/gofiber/fiber/v2/middleware/compress"
    "github.com/gofiber/fiber/v2/middleware/cors"
    "github.com/gofiber/fiber/v2/middleware/helmet"
    "github.com/gofiber/fiber/v2/middleware/logger"
    "github.com/gofiber/fiber/v2/middleware/recover"
    "github.com/gofiber/fiber/v2/middleware/limiter"
)

func main() {
    app := fiber.New(fiber.Config{
        AppName:               "MyAPI v1.0",
        ReadTimeout:           10 * time.Second,
        WriteTimeout:          10 * time.Second,
        IdleTimeout:           120 * time.Second,
        BodyLimit:             4 * 1024 * 1024, // 4MB
        ErrorHandler:          customErrorHandler,
        DisableStartupMessage: true,
    })

    app.Use(recover.New())
    app.Use(helmet.New())
    app.Use(compress.New(compress.Config{Level: compress.LevelBestSpeed}))
    app.Use(cors.New(cors.Config{
        AllowOrigins:     os.Getenv("ALLOWED_ORIGINS"),
        AllowCredentials: true,
        AllowHeaders:     "Origin, Content-Type, Authorization",
    }))
    app.Use(logger.New(logger.Config{
        Format: "${time} | ${status} | ${latency} | ${method} ${path}\n",
    }))
    app.Use(limiter.New(limiter.Config{Max: 100, Expiration: 60 * time.Second}))

    setupRoutes(app)

    log.Fatal(app.Listen(":8080"))
}

Роутинг и группировка

func setupRoutes(app *fiber.App) {
    api := app.Group("/api/v1")

    // Публичные
    api.Post("/auth/login", authHandler.Login)
    api.Post("/auth/refresh", authHandler.Refresh)

    // С JWT middleware
    api.Get("/products", productHandler.List)
    api.Get("/products/:id", productHandler.Get)

    protected := api.Group("/", jwtMiddleware)
    protected.Get("/profile", authHandler.Profile)

    admin := api.Group("/admin", jwtMiddleware, roleMiddleware("admin"))
    admin.Post("/products", productHandler.Create)
    admin.Put("/products/:id", productHandler.Update)
    admin.Delete("/products/:id", productHandler.Delete)
}

Handlers

type ProductHandler struct {
    svc *ProductService
}

type CreateProductInput struct {
    Name       string  `json:"name" validate:"required,min=2,max=255"`
    Price      float64 `json:"price" validate:"required,gt=0"`
    CategoryID *int    `json:"category_id" validate:"omitempty,gt=0"`
}

func (h *ProductHandler) List(c *fiber.Ctx) error {
    page  := c.QueryInt("page", 1)
    limit := c.QueryInt("limit", 20)
    if limit > 100 { limit = 100 }

    catID := 0
    if s := c.Query("category_id"); s != "" {
        catID, _ = strconv.Atoi(s)
    }

    products, total, err := h.svc.List(c.Context(), ListParams{
        Page:       page,
        Limit:      limit,
        CategoryID: catID,
    })
    if err != nil {
        return fiber.ErrInternalServerError
    }

    return c.JSON(fiber.Map{
        "data":       products,
        "pagination": fiber.Map{"page": page, "limit": limit, "total": total},
    })
}

func (h *ProductHandler) Create(c *fiber.Ctx) error {
    var input CreateProductInput
    if err := c.BodyParser(&input); err != nil {
        return fiber.NewError(fiber.StatusBadRequest, err.Error())
    }

    if err := validate.Struct(&input); err != nil {
        return c.Status(fiber.StatusUnprocessableEntity).JSON(fiber.Map{
            "errors": formatValidationErrors(err),
        })
    }

    product, err := h.svc.Create(c.Context(), input)
    if err != nil {
        return mapError(err)
    }

    return c.Status(fiber.StatusCreated).JSON(product)
}

Кастомный error handler

func customErrorHandler(c *fiber.Ctx, err error) error {
    code := fiber.StatusInternalServerError

    var e *fiber.Error
    if errors.As(err, &e) {
        code = e.Code
    }

    // Не раскрываем детали 5xx в production
    if code >= 500 && os.Getenv("APP_ENV") == "production" {
        return c.Status(code).JSON(fiber.Map{"error": "Internal Server Error"})
    }

    return c.Status(code).JSON(fiber.Map{"error": err.Error()})
}

Загрузка файлов

func (h *UploadHandler) Upload(c *fiber.Ctx) error {
    file, err := c.FormFile("file")
    if err != nil {
        return fiber.NewError(fiber.StatusBadRequest, "no file provided")
    }

    if file.Size > 10*1024*1024 {
        return fiber.NewError(fiber.StatusRequestEntityTooLarge, "file too large")
    }

    ext := strings.ToLower(filepath.Ext(file.Filename))
    if !slices.Contains([]string{".jpg", ".jpeg", ".png", ".webp"}, ext) {
        return fiber.NewError(fiber.StatusBadRequest, "unsupported file type")
    }

    f, err := file.Open()
    if err != nil {
        return fiber.ErrInternalServerError
    }
    defer f.Close()

    key := fmt.Sprintf("uploads/%s%s", uuid.New(), ext)
    url, err := h.storage.Upload(c.Context(), key, f, file.Header.Get("Content-Type"))
    if err != nil {
        return fiber.ErrInternalServerError
    }

    return c.JSON(fiber.Map{"url": url})
}

JWT middleware

package middleware

import (
    "strings"

    "github.com/gofiber/fiber/v2"
    "github.com/golang-jwt/jwt/v5"
)

func JWTMiddleware(secret string) fiber.Handler {
    return func(c *fiber.Ctx) error {
        auth := c.Get("Authorization")
        if !strings.HasPrefix(auth, "Bearer ") {
            return fiber.ErrUnauthorized
        }

        token, err := jwt.Parse(auth[7:], func(t *jwt.Token) (interface{}, error) {
            if _, ok := t.Method.(*jwt.SigningMethodHMAC); !ok {
                return nil, fiber.ErrUnauthorized
            }
            return []byte(secret), nil
        })

        if err != nil || !token.Valid {
            return fiber.ErrUnauthorized
        }

        claims := token.Claims.(jwt.MapClaims)
        c.Locals("userID", int(claims["sub"].(float64)))
        c.Locals("role", claims["role"])
        return c.Next()
    }
}

Когда fasthttp ограничивает

fasthttp переиспользует объекты request/context для снижения GC-pressure. Это требует осторожности: нельзя захватывать *fiber.Ctx в горутины без c.Copy(). При передаче контекста в async-операции:

func (h *Handler) AsyncProcess(c *fiber.Ctx) error {
    // НЕ делайте так — ctx будет переиспользован до завершения горутины
    // go func() { h.svc.Process(c) }()

    // Делайте копию
    cc := c.Copy()
    go func() {
        h.svc.ProcessAsync(context.Background(), cc.Body())
    }()

    return c.SendStatus(fiber.StatusAccepted)
}

Сроки разработки

  • Настройка + middleware + роуты — 3–5 дней
  • Handlers + сервисный слой — 1–2 недели
  • Repository + pgx — 3–5 дней
  • Auth + кеш — 3–5 дней
  • Тесты — 1 неделя

API для сайта: 4–8 недель. Fiber хорошо подходит командам с Node.js-бэкграундом, переходящим на Go, и проектам с экстремальными требованиями к RPS.