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.
Microservices, or microservice architecture, is an architectural style that structures an application into a collection of services that are:
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
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.
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.
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:
Now that you have a basic understanding of how Fiber works, let’s build a simple microservice using it.
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!"}, }
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.
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.
main
function in FiberHere’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.
If you visit endpoint localhost:3000/api/v1/post
, you’ll get all the values you defined in your blogs
variable:
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.
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.
Hey there, want to help make our blog better?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowLearn how to manage memory leaks in Rust, avoid unsafe behavior, and use tools like weak references to ensure efficient programs.
Bypass anti-bot measures in Node.js with curl-impersonate. Learn how it mimics browsers to overcome bot detection for web scraping.
Handle frontend data discrepancies with eventual consistency using WebSockets, Docker Compose, and practical code examples.
Efficient initializing is crucial to smooth-running websites. One way to optimize that process is through lazy initialization in Rust 1.80.
6 Replies to "Building microservices in Go with Fiber"
Great tutorial. I found one detail “Final, the app.Listen(“:300″)”. The correct Port in the sample is 3000
Thank you for pointing that out! The typo has been corrected.
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?
This is rather a hello world tutorial about Fiber, you have mentioned nothing about microservices.
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.
The text list of routes is missing the element ‘post’ in path for retrieve single post