Creating a REST API with golang (step 1)
Hey readers! I’ve decided to learn some golang for a sideproject idea (and just because I want to!). So here you have the very first steps I did to create a simple REST API to retrieve the Fornite weapons taken from a CSV file.
Requirements
The first thing you need is… golang. Oh wow, what a surprise. In a Debian environment, just type the following command:
$ sudo apt install golang-go
We will also use mux
as a router/dispatcher. You can install this dependency with the following command:
$ go get github.com/gorilla/mux
Also, get a cool editor to work flawlessly. I am using Atom with the go-plus package.
Development
Our first release will just list the Fornite weapons from a CSV file, nothing else. We will add more features in future steps, like reading from a database, modifying weapons, adding new ones, security stuff… you know what I mean.
Create a folder for your project, and create a main.go
file with the following content:
package main
import (
"encoding/json"
"log"
"net/http"
"github.com/gorilla/mux"
)
func GetWeapons(w http.ResponseWriter, r *http.Request) {
weapons := LoadWeaponsCsv()
json.NewEncoder(w).Encode(weapons)
}
func main() {
router := mux.NewRouter()
router.HandleFunc("/weapons", GetWeapons).Methods("GET")
log.Fatal(http.ListenAndServe(":8000", router))
}
Ok, ok, let me explain you this:
- The main function creates a
mux
router at the very beginning. - The next line adds the
/weapons
URL. When called from a GET request,mux
will execute theGetWeapons
function - After adding all the routes, we serve the router (localhost:8000)
- GetWeapons just loads a
slice
with all the weapons. Then it just returns thatslice
JSON encoded.
Of course, some files are missing here. Be carefull with the capital letters here as names are exported only if it begins with a capital letter (read the golang tour). Let’s start with the weapon.go
file:
package main
type Weapon struct {
Name string `json:"name,omitempty"`
Rarity string `json:"rarity,omitempty"`
FireRate float64 `json:"firerate,omitempty"`
MagSize int `json:"magsize,omitempty"`
ReloadTime float64 `json:"reloadtime,omitempty"`
Multiplier int `json:"multiplier,omitempty"`
DamageBody int `json:"damagebody,omitempty"`
DamageHead int `json:"damagehead,omitempty"`
FallOff string `json:"fallof,omitempty"`
DPSBody int `json:"dpsbody,omitempty"`
DPSHead int `json:"dpshead,omitempty"`
ShotsKillAvgBody float64 `json:"shotskillavgbody,omitempty"`
ShotsKillAvgHead float64 `json:"shotskillavghead,omitempty"`
}
Nothing weird here, just some names and types. Let’s continue with the weapon_loader.go
file:
package main
import (
"bufio"
"encoding/csv"
"fmt"
"io"
"log"
"os"
"strconv"
)
func LoadWeaponsCsv() []Weapon {
var weapons []Weapon
//Name,Rarity,Fire Rate,Mag Size,Reload Time,Multiplier,Damage (Body),Damage (Head),Fall Off,DPS (Body),DPS (Head),Shots/Kill Avg (Body),Shots/Kill Avg (Head)
csvFile, _ := os.Open("fortnite-weapons.csv")
reader := csv.NewReader(bufio.NewReader(csvFile))
for {
line, error := reader.Read()
if error == io.EOF {
break
} else if error != nil {
log.Fatal(error)
}
fireRate, err := strconv.ParseFloat(line[2], 64)
magSize, err := strconv.Atoi(line[3])
reloadTime, err := strconv.ParseFloat(line[4], 64)
multiplier, err := strconv.Atoi(line[5])
damageBody, err := strconv.Atoi(line[6])
damageHead, err := strconv.Atoi(line[7])
dpsBody, err := strconv.Atoi(line[9])
dpsHead, err := strconv.Atoi(line[10])
shotsKillAvgBody, err := strconv.ParseFloat(line[11], 32)
shotsKillAvgHead, err := strconv.ParseFloat(line[12], 32)
if err != nil {
fmt.Println(err)
os.Exit(2)
}
weapons = append(weapons, Weapon{
Name: line[0],
Rarity: line[1],
FireRate: fireRate,
MagSize: magSize,
ReloadTime: reloadTime,
Multiplier: multiplier,
DamageBody: damageBody,
DamageHead: damageHead,
FallOff: line[8],
DPSBody: dpsBody,
DPSHead: dpsHead,
ShotsKillAvgBody: shotsKillAvgBody,
ShotsKillAvgHead: shotsKillAvgHead,
})
}
return weapons
}
For the sake of brevity, I just checked the err
var at the end. As you see here, I just iterate over the CSV file lines and converting the string column values to the needed weapon property type (int or float64).
So, last thing we need: the fortnite-weapons.csv file:
Assault Rifle (M4),Common,5.5,30,2.3,2,30,60,https://i.imgur.com/KfoXkLx.png,165,330,4.75,2.75
Assault Rifle (M4),Uncommon,5.5,30,2.2,2,31,62,https://i.imgur.com/KfoXkLx.png,170.5,341,4.75,2.75
Assault Rifle (M4),Rare,5.5,30,2.2,2,33,66,https://i.imgur.com/KfoXkLx.png,181.5,363,4.75,2.75
Assault Rifle (SCAR),Epic,5.5,30,2.2,2,35,70,https://i.imgur.com/KfoXkLx.png,192.5,385,4.25,2.5
Assault Rifle (SCAR),Legendary,5.5,30,2.1,2,36,72,https://i.imgur.com/KfoXkLx.png,198,396,4.25,2.5
Assault Rifle (Burst),Common,4.06,30,2.9,2,27,54,https://i.imgur.com/Sx9T45c.png,109.62,219.24,5.25,2.75
Assault Rifle (Burst),Uncommon,4.06,30,2.7,2,29,58,https://i.imgur.com/Sx9T45c.png,117.74,235.48,5,2.75
Assault Rifle (Burst),Rare,4.06,30,2.6,2,30,60,https://i.imgur.com/Sx9T45c.png,121.8,243.6,4.75,2.75
Assault Rifle (Burst),Epic,1.75,30,2.5,2,32,64,,56,112,4.75,2.75
Assault Rifle (Burst),Legendary,1.75,30,2.3,2,33,66,,57.75,115.5,4.75,2.75
Assault Rifle (Scoped),Rare,3.5,20,2.3,2,23,46,,80.5,161,6.25,3.5
Assault Rifle (Scoped),Epic,3.5,20,2.2,2,24,48,,84,168,6.25,3.5
Bolt-Action Sniper Rifle,Rare,0.33,1,3,2.5,105,262.5,,34.65,86.625,1.5,1
Bolt-Action Sniper Rifle,Epic,0.33,1,2.8,2.5,110,275,,36.3,90.75,1.5,1
Bolt-Action Sniper Rifle,Legendary,0.33,1,2.7,2.5,116,290,,38.28,95.7,1.5,1
Semi-Auto Sniper Rifle,Epic,1.2,10,2.5,2.5,63,157.5,,75.6,189,2.75,1.25
Semi-Auto Sniper Rifle,Legendary,1.2,10,2.3,2.5,66,165,,79.2,198,2.75,1.25
Crossbow,Rare,0.6,5,2.6,2,75,150,,45,90,2,1.25
Crossbow,Epic,0.6,5,2.5,2,79,158,,47.4,94.8,2,1.25
Hunting Rifle,Uncommon,0.8,1,1.9,2.5,86,215,,68.8,172,2,1
Hunting Rifle,Rare,0.8,1,1.8,2.5,90,225,,72,180,2,1
Tactical Shotgun,Common,1.5,8,6.3,2,67,134,,100.5,201,2.5,1.5
Tactical Shotgun,Uncommon,1.5,8,6,2,70,140,,105,210,2.5,1.5
Tactical Shotgun,Rare,1.5,8,6,2,74,148,,111,222,2.5,1.5
Pump Shotgun,Uncommon,0.7,5,4.8,2,80,160,,56,112,2,1.25
Pump Shotgun,Rare,0.7,5,4.6,2,85,170,,59.5,119,2,1.25
Tactical Submachine Gun,Uncommon,10,30,2.4,2.5,16,40,https://i.imgur.com/0pv2CZd.png,160,400,8.75,3.5
Tactical Submachine Gun,Rare,10,30,2.3,2.5,17,42.5,https://i.imgur.com/0pv2CZd.png,170,425,8,3.5
Tactical Submachine Gun,Epic,10,30,2.2,2.5,18,45,https://i.imgur.com/0pv2CZd.png,180,450,8,3.5
Submachine Gun (Suppressor),Common,9,30,2.2,2,20,40,https://i.imgur.com/IdcVPzm.png,180,360,6.75,3.5
Submachine Gun (Suppressor),Uncommon,9,30,2.1,2,21,42,https://i.imgur.com/IdcVPzm.png,189,378,6.75,3.5
Submachine Gun (Suppressor),Rare,9,30,2,2,22,44,https://i.imgur.com/IdcVPzm.png,198,396,6.5,3.5
Revolver,Common,0.9,6,2.4,2,54,108,https://i.imgur.com/tqZnvxB.png,48.6,97.2,2.75,1.5
Revolver,Uncommon,0.9,6,2.3,2,57,114,https://i.imgur.com/tqZnvxB.png,51.3,102.6,2.75,1.5
Revolver,Rare,0.9,6,2.2,2,60,120,https://i.imgur.com/tqZnvxB.png,54,108,2.75,1.5
Pistol,Common,6.75,16,1.5,2,23,46,https://i.imgur.com/cUntR6r.png,155.25,310.5,6.25,3.5
Pistol,Uncommon,6.75,16,1.5,2,24,48,https://i.imgur.com/cUntR6r.png,162,324,6.25,3.5
Pistol,Rare,6.75,16,1.4,2,25,50,https://i.imgur.com/cUntR6r.png,168.75,337.5,5.25,2.75
Suppressed Pistol,Epic,6.75,16,1.3,2,26,52,https://i.imgur.com/aT5F3c0.png,175.5,351,5.25,2.75
Suppressed Pistol,Legendary,6.75,16,1.3,2,28,56,https://i.imgur.com/aT5F3c0.png,189,378,5.25,2.75
Hand Cannon,Epic,0.8,7,2.1,2,75,150,https://i.imgur.com/UrhFxZg.png,60,120,2,1.25
Hand Cannon,Legendary,0.8,7,2,2,78,156,https://i.imgur.com/UrhFxZg.png,62.4,124.8,2,1.25
We are done! In a terminal type go build
. This will create an executable binary file, so now type ./my-binary-file
(in my case, ./go-fortnite-api
). Now, visit localhost:8000/weapons and… there you have! Our REST API step1 working like a charm.
Next step: connect the API to a SQLite (or something similar) database.
I’ve created a GitHub repository with the work done: https://github.com/jontorrado/go-fortnite-api