DEV Community

Alex Spinov
Alex Spinov

Posted on

Go Fiber Has a Free API — Express.js Speed in Go

Fiber is the Express-inspired web framework for Go — 34K+ GitHub stars, built on Fasthttp (the fastest HTTP engine for Go), and familiar API for Node.js developers transitioning to Go.

Why Fiber?

  • Express-like API — if you know Express, you know Fiber
  • Fasthttp — 10x faster than net/http
  • Zero allocation — minimal memory footprint
  • WebSocket — built-in support
  • Middleware ecosystem — 30+ built-in middleware
  • Template engines — 9 template engines supported

Quick Start

go mod init myapp
go get github.com/gofiber/fiber/v2
Enter fullscreen mode Exit fullscreen mode
package main

import "github.com/gofiber/fiber/v2"

func main() {
    app := fiber.New()

    app.Get("/", func(c *fiber.Ctx) error {
        return c.JSON(fiber.Map{
            "message": "Hello, Fiber!",
        })
    })

    app.Get("/users/:id", func(c *fiber.Ctx) error {
        id := c.Params("id")
        return c.JSON(fiber.Map{"id": id, "name": "Alice"})
    })

    app.Listen(":3000")
}
Enter fullscreen mode Exit fullscreen mode

Route Groups

func main() {
    app := fiber.New()

    // API v1
    v1 := app.Group("/api/v1")
    v1.Get("/users", listUsers)
    v1.Post("/users", createUser)
    v1.Get("/users/:id", getUser)
    v1.Put("/users/:id", updateUser)
    v1.Delete("/users/:id", deleteUser)

    // API v2
    v2 := app.Group("/api/v2")
    v2.Get("/users", listUsersV2)

    app.Listen(":3000")
}
Enter fullscreen mode Exit fullscreen mode

Request Parsing

type CreateUserRequest struct {
    Name  string `json:"name" validate:"required,min=2"`
    Email string `json:"email" validate:"required,email"`
    Age   int    `json:"age" validate:"required,min=18"`
}

func createUser(c *fiber.Ctx) error {
    var req CreateUserRequest
    if err := c.BodyParser(&req); err != nil {
        return c.Status(400).JSON(fiber.Map{"error": "Invalid request body"})
    }

    // Query params
    page := c.QueryInt("page", 1)
    limit := c.QueryInt("limit", 10)

    // Headers
    token := c.Get("Authorization")

    // Cookies
    session := c.Cookies("session_id")

    return c.Status(201).JSON(fiber.Map{
        "user": req,
        "page": page,
    })
}
Enter fullscreen mode Exit fullscreen mode

Middleware

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

func main() {
    app := fiber.New(fiber.Config{
        ErrorHandler: customErrorHandler,
    })

    // Built-in middleware
    app.Use(logger.New())
    app.Use(recover.New())
    app.Use(compress.New())
    app.Use(cors.New(cors.Config{
        AllowOrigins: "https://myapp.com",
        AllowMethods: "GET,POST,PUT,DELETE",
    }))

    // Rate limiting
    app.Use(limiter.New(limiter.Config{
        Max:        100,
        Expiration: 1 * time.Minute,
    }))

    // Custom auth middleware
    app.Use("/api", authMiddleware)

    app.Listen(":3000")
}

func authMiddleware(c *fiber.Ctx) error {
    token := c.Get("Authorization")
    if token == "" {
        return c.Status(401).JSON(fiber.Map{"error": "Unauthorized"})
    }
    // Verify token...
    return c.Next()
}
Enter fullscreen mode Exit fullscreen mode

WebSocket

import "github.com/gofiber/websocket/v2"

app.Use("/ws", func(c *fiber.Ctx) error {
    if websocket.IsWebSocketUpgrade(c) {
        return c.Next()
    }
    return fiber.ErrUpgradeRequired
})

app.Get("/ws/chat", websocket.New(func(c *websocket.Conn) {
    for {
        mt, msg, err := c.ReadMessage()
        if err != nil {
            break
        }
        // Echo message back
        if err = c.WriteMessage(mt, msg); err != nil {
            break
        }
    }
}))
Enter fullscreen mode Exit fullscreen mode

File Upload

app.Post("/upload", func(c *fiber.Ctx) error {
    file, err := c.FormFile("file")
    if err != nil {
        return c.Status(400).JSON(fiber.Map{"error": "No file uploaded"})
    }

    // Save file
    err = c.SaveFile(file, fmt.Sprintf("./uploads/%s", file.Filename))
    if err != nil {
        return c.Status(500).JSON(fiber.Map{"error": "Failed to save file"})
    }

    return c.JSON(fiber.Map{
        "filename": file.Filename,
        "size":     file.Size,
    })
})

// Multiple files
app.Post("/upload-multiple", func(c *fiber.Ctx) error {
    form, err := c.MultipartForm()
    if err != nil {
        return err
    }
    files := form.File["files"]
    for _, file := range files {
        c.SaveFile(file, fmt.Sprintf("./uploads/%s", file.Filename))
    }
    return c.JSON(fiber.Map{"uploaded": len(files)})
})
Enter fullscreen mode Exit fullscreen mode

Fiber vs Gin vs Echo vs Chi

Feature Fiber Gin Echo Chi
Speed Fastest (fasthttp) Fast Fast Fast
API style Express-like Gin Echo stdlib
Stars 34K+ 79K+ 30K+ 18K+
WebSocket Built-in Plugin Plugin Plugin
Template 9 engines 1 (html) Any Any
Middleware 30+ built-in 20+ 20+ Minimal
Learning curve Low (Express devs) Low Low Lowest

Need to scrape data from any website and get it in structured JSON? Check out my web scraping tools on Apify — no coding required, results in minutes.

Have a custom data extraction project? Email me at spinov001@gmail.com — I build tailored scraping solutions for businesses.

Top comments (0)