DEV Community

loading...
Cover image for Go Fiber, performant alternative to Express

Go Fiber, performant alternative to Express

Karan Pratap Singh
Software Engineer and Solutions Architect
Updated on ・4 min read

What is go fiber?

Fiber is a web framework for Go similar to Mux. But it's heavily inspired by Express and that makes it perfect to work with for node developers.

It is built on top of Fasthttp engine, here are some benchmarks. It also has quite a low memory allocation overhead. For example while writing this article it only took around only ~16mb of memory, which was amazing!

In this article let's implement very simple mock api routes to get a feel of the Fiber framework

The code from the article is available in this repository

Getting started

You can install go directly on your system by installing the binary from go docs https://golang.org/doc/install

Alt Text

(optional)

Personally, I like to use docker so I don't have to install anything on my system

Let's pull the golang docker image

docker pull golang
Enter fullscreen mode Exit fullscreen mode

Create your project directory

mkdir go-mock-api
cd go-mock-api
Enter fullscreen mode Exit fullscreen mode

Now we'll bind the port 4000 and mount the current directory (your go project dir) as volume and run our golang image

docker run -itd -p 4000:4000 --name golang -v "$(pwd):/app" golang
Enter fullscreen mode Exit fullscreen mode

Let's run and connect to our running golang container

docker exec -it -w /app golang bash
Enter fullscreen mode Exit fullscreen mode

This should drop us into the golang docker image. Now let's check the version of go and get started

go version
Enter fullscreen mode Exit fullscreen mode

Note: if you're using docker, all the step below are executed inside the golang container

Installation

Let initialise an api module

go mod init api
Enter fullscreen mode Exit fullscreen mode

Install fiber

go get -u github.com/gofiber/fiber/v2
Enter fullscreen mode Exit fullscreen mode

Let's create api.go with a sample hello world server on port 4000 as shown in the repository's readme.

package main

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

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

    app.Get("/", func(ctx *fiber.Ctx) error {
        return ctx.SendString("Hello, World!")
    })

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

Development

Reflex helps with live reload for Go apps, which is great for development. It is quite similar to nodemon, alternatively, you can simply use go run command to run your program.

go get github.com/cespare/reflex
Enter fullscreen mode Exit fullscreen mode

Let's start!

reflex -g '*.go' go run api.go --start-service
Enter fullscreen mode Exit fullscreen mode
Starting service...

 ┌───────────────────────────────────────────────────┐ 
 │                   Fiber v2.13.0                   │ 
 │               http://127.0.0.1:4000               │ 
 │       (bound on host 0.0.0.0 and port 4000)       │ 
 │                                                   │ 
 │ Handlers ............. 2  Processes ........... 1 │ 
 │ Prefork ....... Disabled  PID .............. 3315 │ 
 └───────────────────────────────────────────────────┘ 
Enter fullscreen mode Exit fullscreen mode

Note: Make sure you have PATH exported in your .bashrc or .zshrc file as export PATH=$PATH:$HOME/go/bin/

Now you should be seeing your code running and it should auto reload when you change something, without having to re-run your go program!

Creating a GET route

Let's import fiber

import "github.com/gofiber/fiber/v2"
Enter fullscreen mode Exit fullscreen mode

Add a user route to the main function

app.Get("/user", getUserHandler)
Enter fullscreen mode Exit fullscreen mode

Let's add getUserHandler which will handle the request. Here we will return a mock user.

type User struct {
    Name    string `json:"name"`
    Twitter string `json:"twitter"`
}

func getUserHandler(ctx *fiber.Ctx) error {
    user := User{
        Name:    "Karan",
        Twitter: "karan_6864",
    }

    return ctx.Status(fiber.StatusOK).JSON(user)
}
Enter fullscreen mode Exit fullscreen mode

Creating a POST route

Similarly, let's add a post route to the main function

    app.Post("/user/create", createUserHandler)
Enter fullscreen mode Exit fullscreen mode

Let's add a createUserHandler which will handle the request. Here we will simply parse the body and send it back in the response

func createUserHandler(ctx *fiber.Ctx) error {
    body := new(User)
    err := ctx.BodyParser(body)

    if err != nil {
        ctx.Status(fiber.StatusBadRequest)
        return err
    }

    user := User{
        Name:    body.Name,
        Twitter: body.Twitter,
    }

    return ctx.Status(fiber.StatusOK).JSON(user)
}
Enter fullscreen mode Exit fullscreen mode

Middleware

Let's add logging middleware that comes with fiber

import (
    "github.com/gofiber/fiber/v2/middleware/logger"
)
Enter fullscreen mode Exit fullscreen mode

Add this middleware to main function

app.Use(logger.New())
Enter fullscreen mode Exit fullscreen mode

This should give us some logs as shown below

12:04:01 | 200 |     1ms |      172.17.0.1 | GET     | /user           
12:04:27 | 200 |      0s |      172.17.0.1 | POST    | /user/create   
Enter fullscreen mode Exit fullscreen mode

We can define custom middlewares as well

    app.Use(func(ctx *fiber.Ctx) error {
        fmt.Println("Sample middleware")
        return ctx.Next()
    })
Enter fullscreen mode Exit fullscreen mode

Router

We can organize our routes with Group function, very similar to how we do routing in express.

    userApi := app.Group("/user")

    userApi.Get("/", getUserHander)

    userApi.Post("/create", createUserHandler)
Enter fullscreen mode Exit fullscreen mode

Serving static file

Let's assume we're trying to server public folder, we can simply use the Static function like below

app.Static("/", "./public")
Enter fullscreen mode Exit fullscreen mode

Let's try it out!

Here's our final api.go

package main

import (
    "fmt"

    "github.com/gofiber/fiber/v2"
    "github.com/gofiber/fiber/v2/middleware/logger"
)

type User struct {
    Name    string `json:"name"`
    Twitter string `json:"twitter"`
}

func getUserHander(ctx *fiber.Ctx) error {
    user := User{
        Name:    "Karan",
        Twitter: "karan_6864",
    }

    return ctx.Status(fiber.StatusOK).JSON(user)
}

func createUserHandler(ctx *fiber.Ctx) error {
    body := new(User)
    err := ctx.BodyParser(body)

    if err != nil {
        fmt.Println(err)
        ctx.Status(fiber.StatusBadRequest)
        return err
    }

    user := User{
        Name:    body.Name,
        Twitter: body.Twitter,
    }

    return ctx.Status(fiber.StatusOK).JSON(user)
}

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

    app.Use(logger.New())

    userApi := app.Group("/user")

    userApi.Get("/", getUserHander)

    userApi.Post("/create", createUserHandler)

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

I'm using Insomnia to test out the mock endpoints

Get user

get user

Create user

create user

Feel to reachout to me on twitter if you face any issues.

Feedback is always welcome, Have fun!

Discussion (4)

Collapse
mucorolle profile image
Muco Rolle Tresor

Do you think this resource is good to get started with Go: quii.gitbook.io/learn-go-with-tests/

Collapse
karanpratapsingh profile image
Karan Pratap Singh Author

Looks like a great resource, I'll bookmark it as well, thank you for sharing!

Collapse
mucorolle profile image
Muco Rolle Tresor

Useful as I'm trying to learn some Go.

Collapse
karanpratapsingh profile image
Karan Pratap Singh Author

Thank you!