Learning Golang “Create simple API using Fiber”
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
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