📖 Go Fiber by Examples: How can the Fiber Web Framework be useful?
Tags: go, tutorial, beginners, node
Published: 2021-08-16 15:22:03

## Introduction

Hello and welcome, DEV friends! 👋 

As you probably know, the printed book that we planned to release with **Packt** publisher called **Easy Development with GoFiber** is now canceled. 

> 🤯 There are many reasons for this, both from my side and from the side of this respected publisher, I will not focus on this. 
 
Therefore, I decided to release all of my written material in **free access** as a series of articles in my blog on [Dev.to](https://dev.to/koddr/) for everyone! 😉

Today, I start a new series of articles called **Go Fiber by Examples**, which will be a handbook for those who want to learn the [Fiber](https://github.com/gofiber/fiber) web framework quickly and efficiently while developing a real web application.

## Plan for the Chapter 1

In this first article (or chapter), we will take a look at the history of the **Fiber** web framework, find out which groups of programmers are best suited to it, and see how similar it is to **Node.js** framework **Express**, using real-world examples.

We are going to cover the following main topics 👇

<a name="toc"></a>
### 📝 Table of contents

- [Coming from another programming language or Golang web framework](#coming-from-another-programming-language-or-golang-web-framework)
- [Looking to swap NodeJS for Go](#looking-to-swap-nodejs-for-go)
- [The philosophy behind using Fiber web framework](#the-philosophy-behind-using-fiber-web-framework)
- [A brief comparison with Express](#a-brief-comparison-with-express)
  - [Hello World](#hello-world)
  - [Basic routing and endpoints](#basic-routing-and-endpoints)
  - [Using middleware](#using-middleware)
  - [Serving static files](#serving-static-files)
  - [Working with templates](#working-with-templates)
- [Summary](#summary)

<a name="#coming-from-another-programming-language-or-golang-web-framework"></a>
## Coming from another programming language or Golang web framework

If you come from another language (such as **Python**, **Ruby**, or **JavaScript**), the **Fiber** web framework will help you to smoothly enter into the **Go** programming language. 

It has very familiar elements and is designed to make the product development process as easy as possible for developers of different skill levels from other programming languages. 

For developers who are already working with other **Go** web frameworks or API tools, **Fiber** can offer the following benefits:

- Extreme performance and low memory footprint
- Rapid server-side programming
- Built-in middleware for most tasks
- Rich and robust routing
- Easy serve static files and work with databases
- Support of all popular template engines
- ...and much, much more to talk about in this series!

A friendly and supportive **Fiber** community around the World has already translated basic documentation into **15** different languages and is ready to support you in [issues](https://github.com/gofiber/fiber/issues) of the project repository on **GitHub**.

[↑ Table of contents](#toc)

<a name="#looking-to-swap-nodejs-for-go"></a>
## Looking to swap NodeJS for Go

New gophers that make the switch from [Node.js](https://nodejs.org/) to **Golang** are dealing with a learning curve before they can start building their web applications, APIs, or microservices. 

**Fiber** inspired by [Express](https://expressjs.com/), the most popular web framework on the Internet. Its authors combined the ease of **Express** and the raw performance of **Go**. 

And we will be surprised at how easy it is to make the transition from one language to a wholly different one, thanks to learning just the **Fiber** Web Framework!

> 🌐 **Note**: Also, I recommend visiting the **GitHub** repository by Miguel Mota called [Golang for Node.js Developers](https://github.com/miguelmota/golang-for-nodejs-developers). It describes the basic principles for a smoother transition of your backend from **JavaScript** to **Go** in a fairly straightforward way.

Therefore, if you have ever implemented a web application in **Node.js** (using **Express** or similar), then many methods and principles will seem very common to you.

We will discuss this in more detail near the end of this article.

[↑ Table of contents](#toc)

<a name="#the-philosophy-behind-using-fiber-web-framework"></a>
## The philosophy behind using Fiber web framework

**Fiber**, as a web framework, was created with the idea of minimalism and follows the [UNIX way](https://en.wikipedia.org/wiki/Unix_philosophy), so that new gophers can quickly enter the world of Go with a warm and trusted welcome. That’s why **Fiber** is a very versatile **Go** framework.

But the main focus of its application is to create complete all-in-one web applications, like [Django](https://www.djangoproject.com/) in **Python** or [Ruby on Rails](https://rubyonrails.org/) in **Ruby**, and efficient high-performance REST APIs, like [FastAPI](https://fastapi.tiangolo.com/) for **Python**. 

This does not mean that you cannot create microservices or adapters for your infrastructure or even desktop network apps or else on **Fiber**. Absolutely no! Such areas are simply not a priority for the authors of this framework. But they always listen to its users in issues on **GitHub** repository, [Discord channel](https://gofiber.io/discord), and all over the Internet.

The authors want to create a fast, flexible, and friendly **Golang** web framework for any task, deadline, and developer skill. Just like **Express** framework does in the **JavaScript** world.

[↑ Table of contents](#toc)

<a name="#a-brief-comparison-with-express"></a>
## A brief comparison with Express

Being inspired by **Express**, the **Fiber** web framework may seem very familiar to you. We will break down the most basic things in the next sections, where you can see them for yourself. 

> 👌 **Note**: Don't worry if you have never worked with **Go** or **JavaScript**, we have left comprehensive comments in the code examples below to help you get oriented.

<a name="#hello-world"></a>
### Hello World

A classic example for every programming language or web framework is the minimally working **Hello World** program. Well, let's not deny ourselves that!

First, let's take a look at **Express**:

```js
// ./js/hello_world.js

const express = require("express"); // add Express library
const app = express(); // create a new Express instance

// Create a new endpoint
app.get("/", (req, res) => {
  res.send("Hello World!"); // send text
});

// Start server on port 3000
app.listen(3000);
```

Straightforward, isn't it? Just a couple of lines of code and a full-fledged web server is ready to receive users on the specified endpoint on port `3000`.

And here's how the same functionality can be implemented with **Fiber**:

```go
// ./go/hello_world.go

package main

import "github.com/gofiber/fiber/v2" // add Fiber package

func main() {
  app := fiber.New() // create a new Fiber instance

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

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

Except for some **JavaScript** or **Go**-specific blocks at the beginning of the program, the code reads, feels, and works the same under the hood. And this state will follow us in almost all the code examples in this series.

[↑ Table of contents](#toc)

<a name="#basic-routing-and-endpoints"></a>
### Basic routing and endpoints

As you know, any web application, microservice, or API includes a routing system based on endpoints describing an [HTTP method](https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Request_methods) and a handler function, which will be executed only after this endpoint receives a request from the client-side.

In the preceding **Hello World** program, we already touched the `app.get(path, () => {})` (in case of **Express**) and `app.Get(path, func() error {})` (in case of **Fiber**) endpoints, which serve the HTTP GET method and return a plain string when requested. 

Let’s take a look at the other HTTP methods which we can use to describe the endpoint in our web application. Let's start, per tradition, with the **Express**:

```js
// ./js/routing.js

// Endpoint for POST method
app.post("/", (req, res) => {
  // function that stores a new data
});

// Endpoint for PUT method
app.put("/", (req, res) => {
  // function that replaces the existing data
});

// Endpoint for PATCH method
app.patch("/", (req, res) => {
  // function that replaces part of the existing data
});

// Endpoint for DELETE method
app.delete("/", (req, res) => {
  // function that deletes the data
});
```

It might seem that these HTTP methods are not enough to describe the endpoints of your web application, but in fact, **Express**, and **Fiber** support many more request HTTP methods.

> ☝️ **Note**: We have only described the most basic ones!

Now let's take a look at how the same basic HTTP methods look in **Fiber**:

```go
// ./go/routing.go

// Endpoint for Post method
app.Post("/", func(c *fiber.Ctx) error {
  // function that stores a new data
})

// Endpoint for PUT method
app.Put("/", func(c *fiber.Ctx) error {
  // function that replaces the existing data
})

// Endpoint for PATCH method
app.Patch("/", func(c *fiber.Ctx) error {
  // function that replaces part of the existing data
})

// Endpoint for DELETE method
app.Delete("/", func(c *fiber.Ctx) error {
  // function that deletes the data
})
```

Again, except for some blocks specific to each programming language, the code reads and works the same.

[↑ Table of contents](#toc)

<a name="#using-middleware"></a>
### Using middleware

The middleware functions have access to the HTTP request and response objects and the next middleware function. They can perform the following tasks:

- Execute any code we need
- Make any changes and modifications to the request and response objects
- Complete the request-response loop
- Call the next middleware function that is in the stack

We are not going to delve into middleware now. Our goal is only to compare the technical design of these web frameworks. 

> 👌 **Note:** We will return to middleware in later articles of this series.

So, here is an example of a middleware function for the **Express** framework that outputs the current date and time to the browser console and simply passes the request to the next endpoint:

```js
// ./js/middleware.js

// Middleware function
app.use(function (req, res, next) {
  // print current date and time to console
  console.log("Date:", Date.now());

  // passing the request to the next endpoint
  next();
});
```

And this is how the same middleware will work with **Fiber**, but the date and time will be output to the normal terminal instead of the browser console:

```go
// ./go/middleware.go

// Middleware function
app.Use(func(c *fiber.Ctx) error {
  // print current date and time to console
  fmt.Println("Date:", time.Now())

  // passing the request to the next endpoint
  return c.Next()
})
```

Once again, we saw similarities between these web frameworks.

[↑ Table of contents](#toc)

<a name="#serving-static-files"></a>
### Serving static files

If we want to create a [Single-Page Application](https://en.wikipedia.org/wiki/Single-page_application) rather than an ordinary web application, we will need to be able to request a directory with static files. 

These files are usually:

- Images
- CSS files
- JavaScript files
- HTML files
- Template and other downloadable files

The process of working with them is based on this scheme:

1. Define a folder to store static files.
2. Specify it as a mount point in the web application.
3. In the HTML file (or template) we make references to this mount point.

Let's look at a small example to get an understanding.

If we store statics in the `./public` folder at the root of our directory, then using the Express built-in `express.static()` function, we can mount it at `/static` address as follows:

```js
// ./js/static.js

app.use(
  "/static", // mount address
  express.static("public") // path to the file folder
);
```

And here's a sample code for **Fiber** that will do the same thing for us:

```go
// ./go/static.go

app.Static(
  "/static",  // mount address
  "./public", // path to the file folder
)
```

As a result, all static files for both **Express** and **Fiber** will be available at the following address:

```
http://localhost:3000/static/images/background.jpg 
http://localhost:3000/static/css/style.css 
http://localhost:3000/static/js/app.js 
http://localhost:3000/static/index.html
```

With this approach, we can easily set up a proxy server, such as [NGINX](https://nginx.org), to send static files more efficiently.

[↑ Table of contents](#toc)

<a name="#working-with-templates"></a>
### Working with templates

When we build a web application that not only has to return content in JSON format but also has to be able to render templates with that content, template engines come to the rescue. 

Both web frameworks support a huge number of template engines right out of the box: [Pug](https://pugjs.org/), [Jade](https://jade-lang.com/), [Mustache](https://mustache.github.io/), [Handlebars](https://handlebarsjs.com/), and many others. Let's take a look at the **Pug** engine to see how a template renders in **Express** works:

```js
// ./js/templates.js

// Initialize Pug template engine for rendering
app.set("view engine", "pug");

// Initialize templates folder
app.set("views", "./views");

// Create a new endpoint
app.get("/", (req, res) => {
  // rendering the "index" template with content passing
  res.render("index", {
    title: "Hey!",
    message: "This is the index template.",
  });
});
```

For **Fiber**, the same example will be a little more complicated but will remain just as familiar. The reason for this is that the configuration of the application cannot be changed after the **Fiber** instance has been created. It is read-only. 

```go
// ./go/templates.go

// Initialize Pug template engine in ./views folder
engine := pug.New("./views", ".pug")

// Create a new Fiber instance
app := fiber.New(fiber.Config{
  Views: engine, // set template engine for rendering
})

// Create a new endpoint
app.Get("/", func(c *fiber.Ctx) error {
  // rendering the "index" template with content passing
  return c.Render("index", fiber.Map{
    "Title":   "Hey!",
    "Message": "This is the index template.",
  })
})
```

> ⚙️ **Note**: Both frameworks will only look for templates with `*.pug` extension in the `./views` folder of the current directory. If this folder does not exist or does not contain a file named `index.pug`, an error will happen.

Even though Express and **Fiber** written in different programming languages and by different development teams, they have a very similar technical design of built-in functions and working principles. This is what makes **Fiber** so special among many **Go**-based web frameworks. 

We will explain this in more detail later in the future articles.

[↑ Table of contents](#toc)

<a name="#summary"></a>
## Summary

We hope this article of the series has shown you a different side of the **Go** language, if you've only ever written code for your web applications in **JavaScript** before. 

Furthermore, we do numerous new things:

- We learned what **Fiber** is good for and where it can be used effectively.
- We compared the basic functions of the Express and **Fiber** web frameworks. 
- Dismantled the routing system of web frameworks using simple examples.
- Understood what middleware is and how to work with it in Fiber. 
- We looked at an example of how **Fiber** works with static files. 
- We found out what popular template engines **Fiber** supports out of the box and how to work with them.

In the next articles, we will get even closer to the inner workings of the **Fiber** web framework, its built-in components and methods.

[↑ Table of contents](#toc)

<a name=""></a>
## Photos and videos by

- Janko Ferlič feat. Vic Shóstak https://unsplash.com/photos/sfL_QOnmy00

<a name=""></a>
## P.S.

If you want more articles (like this) on this blog, then post a comment below and subscribe to me. Thanks! 😻

And of course, you can help me make developers' lives even better! Just connect to one of my projects as a contributor. It's easy!

My projects that need your help (and stars) 👇

- 🔥 [gowebly][gowebly_url]: A next-generation CLI tool for easily build amazing web applications with Go on the backend, using htmx & hyperscript and the most popular atomic/utility-first CSS frameworks on the frontend.
- ✨ [create-go-app][cgapp_url]: Create a new production-ready project with Go backend, frontend and deploy automation by running one CLI command.
- 🏃 [yatr][yatr_url]: Yet Another Task Runner allows you to organize and automate your routine operations that you normally do in Makefile (or else) for each project.
- 📚 [gosl][gosl_url]: The Go Snippet Library provides snippets collection for working with routine operations in your Go programs with a super user-friendly API and the most efficient performance.
- 🏄‍♂️ [csv2api][csv2api_url]: The parser reads the CSV file with the raw data, filters the records, identifies fields to be changed, and sends a request to update the data to the specified endpoint of your REST API.
- 🚴 [json2csv][json2csv_url]: The parser can read given folder with JSON files, filtering and qualifying input data with intent & stop words dictionaries and save results to CSV files by given chunk size.

<!-- Footer links -->

[gowebly_url]: https://github.com/gowebly
[cgapp_url]: https://github.com/create-go-app
[yatr_url]: https://github.com/koddr/yatr
[gosl_url]: https://github.com/koddr/gosl
[csv2api_url]: https://github.com/koddr/csv2api
[json2csv_url]: https://github.com/koddr/json2csv