Building microservices in Go with Fiber
Tags: go
Published: 2022-03-22 15:04:06

**Written by [Subha Chanda](https://blog.logrocket.com/author/subhachanda/)✏️**

Go, designed by Google engineers Robert Griesemer, Rob Pike, and Ken Thompson in 2007, is known for being fast and reliable, which is why it remains popular for web developers today. Go, combined with the power of microservices, helps build fast, efficient, and robust applications.

In this article, you’ll learn how to build microservices in Go using a package called [Fiber](https://gofiber.io/), a Go framework that is inspired by the Node.js Express framework. It is built on top of the [Fast](https://github.com/valyala/fasthttp) HTTP package, known for being the fastest HTTP engine for Go.

## What are microservices?

Microservices, or microservice architecture, is an architectural style that structures an application into a collection of services that are:

*   Maintainable
*   Testable
*   Loosely coupled
*   Independently deployable
*   Owned by a small team

*A microservices architecture is a type of application architecture where the application is developed as a collection of services. It provides the framework to develop, deploy, and maintain microservices architecture diagrams and services independently ([Google](https://cloud.google.com/learn/what-is-microservices-architecture)).*

![Microservice Architecture Wireframe](https://blog.logrocket.com/wp-content/uploads/2022/03/microservice-architecture-wireframe.png) The above diagram shows what a microservices architecture looks like. Notice that all the microservices are connected through an API gateway that communicates with the client.

Microservice architecture helps speed up the development process, and, because every service is minor, building the services can be done by small teams. It’s also easier to maintain and test the codes with a microservice.

Because all services are independent, it also offers improved fault isolation, so, if a single service fails, the whole system doesn't necessarily stop working.

## What is Fiber?

Fiber is a web framework heavily inspired by [Express](https://expressjs.com/). If you are coming from Node.js, Python, or Ruby, you'll find Fiber extremely easy to get started with. Go is fast, low on memory footprint, and highly performant, meaning it also makes the Fiber framework fast.

Fiber provides a robust routing mechanism and middleware is built-in for most tasks, and simplifies serving static assets or connecting to a database.

Fiber has thorough [documentation](https://docs.gofiber.io/), support, and a [great community](https://discord.com/invite/bSnH7db). Even though the primary use case for Fiber is to build an all-in-one web framework, it's also possible to create microservices with it.

## How to use Fiber

Before moving directly to building a microservice using Fiber, let's look at a simple Hello World example. To get started, open a folder to save your file using your favorite text editor.

To install any dependency in this folder, initialize the directory using `go mod`. Run this command in your terminal: `go mod init example.com/username/folder`, where `example.com` can be any website where you store your code, the `username` is your username, and the `folder` is the folder name in which you want to keep the files.

Running this command will create a `go.mod` file in your working directory. This [`go.mod`](https://go.dev/doc/tutorial/create-module) [file](https://go.dev/doc/tutorial/create-module) tracks all the dependencies used in the project.

Now that the `go.mod` file is created, you are ready to install Fiber as a dependency. Run `go get -u github.com/gofiber/fiber/v2` in your terminal to download the dependency.

Let's look at the `Hello World` example now to understand the basics of Fiber.

```go
package main

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

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

    // Create a new endpoint
    app.Get("/", func(c *fiber.Ctx) error {
        return c.SendString("Hello World!")
    })

    // Start server on port 3000
    app.Listen(":3000")
}
```

In the above example, the `app := fiber.New()` is initializing a new instance of Fiber. The `app.Get` method sets a Get request to the root route `/`, and a string is set up as a response in the root route sending the text `Hello World!`.

Finally, the `app.Listen(":3000")` is starting a server at port `3000`. The above code will give the output below:

![Hello World Output](https://blog.logrocket.com/wp-content/uploads/2022/03/hello-world-output.png)

Now that you have a basic understanding of how Fiber works, let's build a simple microservice using it.

## Building microservices in Go using Fiber

The microservice we’ll build consists of two routes: the first route returns all the blog posts, and the second route returns the post depending on the ID.

```go
/api/v1/post - returns all posts
/api/v1/:id - returns post that matches the ID
```

Because this microservice is simple to build, we will not refactor the code into multiple files. Instead, the code will be a single `main.js` file. Also, we will not use a database in this use case.

In `main.js`, create a struct — which is a collection of fields — called `Blog`.

```go
type Blog struct {
    Id    int    `json:"id"`
    Title string `json:"title"`
    Body  string `json:"body"`
}
```

The above struct resembles a blog post. Each blog post will contain an ID, a title, and a body. `json:` defines the field names to show when it's rendered as JSON.

Next, create a variable called `blogs` of type `Blog` and define the values in this variable:

```go
type blogPosts []Blog

var blogs = blogPosts{
    {Id: 1, Title: "Hello", Body: "Hello World!"},
    {Id: 2, Title: "Fiber", Body: "Fiber is fast!"},
    {Id: 3, Title: "Microservice", Body: "Microservice is awesome!"},
} 
```

## Defining routes in Go

Now, let’s define the routes.

```go
func setupRoutes(app *fiber.App) {
    app.Get("/api/v1/post", GetPosts)
    app.Get("/api/v1/post/:id", GetPost)
}
```

A function is created with the name `setupRoutes`. It takes an argument of `fiber.App`. Here, we are defining the routes. This function maps the endpoints with the functions passed as the second parameter.

`app.Get("/api/v1/post", GetPosts)` tells that upon a get request to route `/api/v1/post`, the `GetPosts` function will be called. And, on a get request to the route `/api/v1/post/:id`, where `id` is a variable, the `GetPost` function will be called.

Let's define the functions now. The `GetPost` function is a simple function that returns all the data from the `blogs` variable.

```go
func GetPosts(c *fiber.Ctx) error {
    return c.JSON(blogs)
}
```

<span class="inline-code author-d-1gg9uz65z1iz85zgdz68zmqkz84zo2qoxwekhz84zz80zz69zhj0ez73zh8z69zi8z122zjpq1fz72zqz72z5z65zl5a">[fiber.Ctx](https://docs.gofiber.io/api/ctx#context)</span> <span class=" author-d-1gg9uz65z1iz85zgdz68zmqkz84zo2qoxwekhz84zz80zz69zhj0ez73zh8z69zi8z122zjpq1fz72zqz72z5z65zl5a">returns a</span> <span class="inline-code author-d-1gg9uz65z1iz85zgdz68zmqkz84zo2qoxwekhz84zz80zz69zhj0ez73zh8z69zi8z122zjpq1fz72zqz72z5z65zl5a">[fasthttp.RequestCtx](https://pkg.go.dev/github.com/valyala/fasthttp#RequestCtx)</span> <span class=" author-d-1gg9uz65z1iz85zgdz68zmqkz84zo2qoxwekhz84zz80zz69zhj0ez73zh8z69zi8z122zjpq1fz72zqz72z5z65zl5a">instance.</span> It contains the incoming request and manages the outgoing response. The function returns the `blogs` variable by converting the variable to JSON.

Now we’ll build the `GetPost` function. Let’s look at the function first:

```go
func GetPost(c *fiber.Ctx) error {
    id := c.Params("id")
    i, err := strconv.Atoi(id)
    if err != nil {
        return c.JSON(fiber.Map{"error": "Invalid ID"})
    }
    for _, s := range blogs {
        if s.Id == i {
            return c.JSON(s)
        }
    }
    return c.JSON(fiber.Map{"error": "Post not found"})
}
```

The `c.Params` method gets the parameters passed in the route. The first step in this function is to store the parameter into a variable. The variable is defined as `id` and it stores the parameter `id`.

Because this is a simple example, we'll use a `for` loop to find the data. When working with a real database, you'll have methods to find the specific data.

By default, the `Params` method returns a string. You'll have to convert the string to an integer. Otherwise, it'll be impossible to compare an integer value with a string because the `Id` type of the `Blog` struct is of type `int`.

However, you can use the [`ParamsInt`](https://docs.gofiber.io/api/ctx#paramsint) method to get an integer value from the route parameters using `id, err := c.ParamsInt("id")`. For this example, we’ll stick with the `Params` method.

The `Atoi` (“ASCII to integer”) method from the `strconv` package will be used to convert the value to an integer. This function returns two values, the converted result and the error.

The `i` and `err` variables store the converted value and the error, respectively. If the `err` variable is not `nil`, there is some error and the function will return a JSON value with the key-value pair of `"error": "Invalid ID"`.

If the `err` is nil, the process jumps into the `for` loop. Inside the `for` loop, the ID value received from the parameter is compared with the IDs of the posts from the `blogs` variable. If the two values match, it'll return the particular struct value. In any other case, the function will return `"error": "Post not found"`.

That was the last function needed for the routes. Now, we can look at the `main` function.

## The `main` function in Fiber

Here's how the `main` function looks:

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

    // Create a new endpoint
    app.Get("/", func(c *fiber.Ctx) error {
        return c.JSON(fiber.Map{"data": "Hello World!"})
    })

    setupRoutes(app)
    // Start server on port 3000
    app.Listen(":3000")
}
```

First, Fiber is initialized with the `fiber.New()` method. Then, as a test route, the root route is set where it returns a map value of `"data": "Hello World!"`. You've already seen the `setupRoutes` function above. The `setupRoutes` function holds the routes of our app.

The `app` instance is passed in this function to initialize the routes. Finally, a server is started at port `3000` using the `app.Listen(":3000")`.

Now, we’re ready! If you run the `main.go` file from the terminal using `go run main.go`, it will start the server at your localhost port `3000`. You can now test it using [Postman](https://www.postman.com/) or any API client you prefer.

## Testing Fiber using Postman

If you visit endpoint `localhost:3000/api/v1/post`, you'll get all the values you defined in your `blogs` variable:

![Blogs Variable Values](https://blog.logrocket.com/wp-content/uploads/2022/03/blogs-variable-values.png)

Visiting the route `localhost:3000/api/v1/post/:id`, where the `id` variable is an ID available in the blog posts, will return the specific post.

![ID Variable](https://blog.logrocket.com/wp-content/uploads/2022/03/id-variable.png)

## Conclusion

In this article, we covered the basics of microservice architecture and learned how to build microservices in Go using Fiber.

Fiber is fast and resembles the Node.js express framework, making it easier for a Node.js developer to [transition to using Go](https://github.com/miguelmota/golang-for-nodejs-developers). The complete code discussed in this article can be found in [this repo](https://github.com/nemo0/go-fiber-example).

---

## [LogRocket](https://logrocket.com/signup/): Full visibility into your web apps

![LogRocket signup](https://blog.logrocket.com/wp-content/uploads/2017/03/1d0cd-1s_rmyo6nbrasp-xtvbaxfg.png)

[LogRocket](https://logrocket.com/signup/) is a frontend application monitoring solution that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.

In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single-page and mobile apps.

[Try it for free](https://logrocket.com/signup/).