Subha Chanda Subha is a web developer who is passionate about learning and experimenting with new things.

Building microservices in Go with Fiber

5 min read 1593

Go Logo

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, a Go framework that is inspired by the Node.js Express framework. It is built on top of the Fast 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

Microservice Architecture Wireframe
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. 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, support, and a great community. 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 file 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.

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

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.

/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.go file. Also, we will not use a database in this use case.

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



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:

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.

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.

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

fiber.Ctx returns a fasthttp.RequestCtx instance. 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:

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 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.


More great articles from LogRocket:


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:

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 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

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

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. The complete code discussed in this article can be found in this repo.

Subha Chanda Subha is a web developer who is passionate about learning and experimenting with new things.

6 Replies to “Building microservices in Go with Fiber”

  1. Hi, I am new to GO. Just started learning it. I would like to know if Fiber has any advantages over the GIN library from the official documentation? It reminds me all lot of express as well. Except for minor differences it reads the same in your examples. Is there any reason to choose Fiber over GIN?

  2. This is rather a hello world tutorial about Fiber, you have mentioned nothing about microservices.

    1. Thanks for reading and for your comment. The “Hello, World!” example is meant to lay a foundation for the “Building microservices in Go using Fiber” section, which walks through the steps of building a simple microservice with Fiber.

  3. The text list of routes is missing the element ‘post’ in path for retrieve single post

Leave a Reply