Learning Golang “Create simple API using Fiber”

Ari Nurcahya
6 min readDec 26, 2020

Hello this is my second article that I’ve written using english. and I’m still learning my grammar so it’s so excited to using english when writing an articles.

so what is Fiber? Fiber is Golang Framework that built on top of FastHTTP and it inspired by expressjs. quoted by the documentation

Fiber is an Express inspired web framework built on top of Fasthttp, the fastest HTTP engine for Go. Designed to ease things up for fast development with zero memory allocation and performance in mind

when I decided to use golang as my language I found Fiber, and it helped me to learning more about golang, because I’m a Nodejs developer. when I saw the routing, middleware, handler, etc. it’s similar with expressjs.

oh ya, Fiber version when I learn and used Fiber as my main framework for my last project is 1.*, and the lastest version of Fiber is 2.* now.

What will we learn on this article:

  • Setup project using Fiber
  • Make API with Fiber with statics data with no database use here

Setup for my Machine

  • Machine: MacBook Pro Retina 2015
  • OS: macOS 11.2 BigSur
  • Text Editor: Visual Studio Code
  • Golang: 1.14.1
  • Terminal: iTerm

First Step is Installing Fiber and setup the projects

Oke the first thing that you need to do is make your folder projects for example I’ll use my documents/projects/learn-fiber directory

so I’ll open my terminal and typed

cd documents/projects/

and because I’ve never created learn directory at projects directory I’ll typed here

mkdir learn-fiber

then I opened the directory

cd learn-fiber

after that I’ll create go modules

go mod init learn-fiber
Yay succeesfully

and installing fiber on my machine at the go modules

go get github.com/gofiber/fiber/v2

yay you successfully installing fiber on your machine. then just open your project using your loving text editor, here I’m use Visual Studio Code as my primary Text Editor.

Project structure

our app project structure will be like here

Because it is just a simple API in fiber so I didn’t make it as a complex folder structure. so what is that

  • Handlers

Handlers is a folder that will be a http handler, if you’re familiar with MVC pattern the handlers is just a controller in MVC pattern

  • localdata

because the app that we want to build still doesn’t use any database so we will declare static data. and all of the data will be placed at localdata. localdata has 2 file, data.go and user.model.go. data.go is a manipulation function, like a function for initialize data, and CRUD function. then user.model.go is a model

  • routes

routes is a folder for storing routes handler

Create Function that will serve all code

first we need to create server.go in our project directory, and the code will be like here

first we must create new instance from fiber, then we must pass it as a parameter in a routes function then we must listen the connection

Create Routes Function

here is a Routes function, in routes function we will define the parameter, and it is a pointer. why we must use pointer in the param? because when we define parameter as a pointer we can change data without returning it. because we just fill the variable memory with a new data, not change the value, but change the value of the memory address

Create Statics Datastorage

because our simple project didn’t use any database, so we must use statics data in our app. first we must create a struct for our data structure

then we mustcreate a new file called as data.go

then we must create a interface and struct

type Data interface { 
GetData() []UserModel
GetDataById(id int) UserModel
DeleteData(id int) []UserModel
InsertData(UserModel) []UserModel
UpdateDataById(id int, user UserModel) []UserModel
}
type data struct {
userList []UserModel
}

then we must create function for initialize the data

func InitData() Data { 
return &data{
userList: []UserModel{
UserModel{
ID: 1,
Name: "A",
Age: 18,
Gender: "Male",
},
UserModel{
ID: 2,
Name: "Chi",
Age: 17,
Gender: "Female",
},
UserModel{
ID: 3,
Name: "Shintaro",
Age: 18,
Gender: "Male",
},
UserModel{
ID: 4,
Name: "Ayano",
Age: 18,
Gender: "Female",
},
},
}
}

then we must describe all of our abstract function in our interface.

first create GetData function

GetData function is a function that will returning all of userList data.

func (d *data) GetData() []UserModel { 
return d.userList
}

GetDataById

this function will return one of data based on their id

func (d *data) GetDataById(id int) UserModel { 
var foundIn int
var isFound bool
isFound = false
for idx, val := range d.userList {
if val.ID == id {
foundIn = idx
isFound = true
}
}
if isFound {
return d.userList[foundIn]
}
return UserModel{}
}

DeleteData

this function will return a list of data without data that had deleted before

func (d *data) DeleteData(id int) []UserModel { 
var foundIn int
var isFound bool
isFound = false
for idx, val := range d.userList {
if val.ID == id {
foundIn = idx
isFound = true
}
}
if isFound {
d.userList[foundIn] = d.userList[len(d.userList)-1]
d.userList[len(d.userList)-1] = UserModel{}
d.userList = d.userList[:len(d.userList)-1]
return d.userList
}
return []UserModel{}
}

InsertData

This function will returning a List data with new data that had inserted before

func (d *data) InsertData(user UserModel) []UserModel { 
user.ID = len(d.userList)
return append(d.userList, user)
}

UpdateData

This function will return a userList data with a updated data by their id

func (d *data) UpdateDataById(id int, user UserModel) []UserModel {  
var foundIn int
var isFound bool
isFound = false
for idx, val := range d.userList {
if val.ID == id {
foundIn = idx isFound = true
}
}
if isFound {
d.userList[foundIn].Name = user.Name
d.userList[foundIn].Age = user.Age
d.userList[foundIn].Gender = user.Gender
}
return d.userList
}

And here is the full code

Create Handler function

in handler function we will have 5 main function, what are that?

  • ReadData
  • ReadDataById
  • InsertData
  • DeleteData
  • PatchData

GetData

func ReadData(ctx *fiber.Ctx) error {   data := localdata.InitData()   return ctx.JSON(data.GetData())}

first we must create a function with a parameter and the data type is fiber.Ctx, and will returning an error. in Fiber version 2 we must return an error in our routes handler.

and the localdata.InitData() is a initialization from our data.go file, and it should be used at of all handler

then just return ctx.JSON(), why we returning it? at the implement we just returning an error. ctx.JSON will returning an error then we just passed it to our handler as a return statement. in Fiber v1 it’s not be implement so just type as ctx.JSON() without return statement. but in Fiber v2 it’s important

ReadDataById

func ReadDataById(ctx *fiber.Ctx) error {   id, _ := strconv.Atoi(ctx.Params("id"))   data := localdata.InitData()   return ctx.JSON(data.GetDataById(id))}

first we must convert the params data to int, use strconv library and in this library there are a function called as Atoi, this function is using for converting string to integer. and this function returning multiple value, the value and the error.

InsertData

func InsertData(ctx *fiber.Ctx) error {   data := localdata.InitData()   user := new(localdata.UserModel)   fmt.Println([]byte(ctx.Body()))   if err := ctx.BodyParser(user); err != nil {      return err   }   users := data.InsertData(localdata.UserModel{      Name:   user.Name,      Gender: user.Gender,      Age:    user.Age,   })   return ctx.JSON(users)}

in this function we must create a point object, using new keyword. and then because it’s a pointer you cannot be passed it to InsertData function from data’s package. after you make a new pointer object you should parse request body to your object using this statement err := ctx.BodyParser(user), this is built in function from fiber. and it’s returning an error.

DeleteData

func DeleteData(ctx *fiber.Ctx) error {   id, _ := strconv.Atoi(ctx.Params("id"))   data := localdata.InitData()   return ctx.JSON(data.DeleteData(id))}

first you must convert and get your parameter use this statement id, _ := strconv.Atoi(ctx.Params(“id”)), and then just passed the id to DeleteData function from data’s package

PatchData

func PatchData(ctx *fiber.Ctx) error {   id, _ := strconv.Atoi(ctx.Params("id"))   data := localdata.InitData()   user := new(localdata.UserModel)   if err := ctx.BodyParser(user); err != nil {      return err   }   users := data.UpdateDataById(id, localdata.UserModel{      Name:   user.Name,      Gender: user.Gender,      Age:    user.Age,   })   return ctx.JSON(users)}

first you must convert and get your parameter use this statement id, _ := strconv.Atoi(ctx.Params(“id”)), after that you must create a new pointer object using new statment, and parsing your request body to your pointer, and then just passed id, and the data to your UpdateDataById function.

and here is a final code for handler file

oke, that’s all how to create a simple API using fiber go. I hope this article is help you to starting learning Fiber go for your projects. and here is a final code on my github

https://github.com/NurcahyaAri/recipes-build-simple-api-using-fiber

--

--