Api with go and sqlite
- compiles to machine code
- garbage collected
- goroutines / green threads
- channels for thread coordination
- statically typed
- no classes or type inheritance
- interfaces
- simple language, simple tools
mkdir fiberapi
cd fiberapi
go
go version
go mod init "github.com/OzanOcak/fiberapi"
go get -u gorm.io/driver/mysql
go get -u gorm.io/gorm
go get github.com/gofiber/fiber/v2
Fiber is a Go web framework built on top of Fasthttp, the fastest HTTP engine for Go.
Gorm is a ORM library for golang
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
package main
import (
"log"
"github.com/gofiber/fiber/v2"
)
func aloha(arg *fiber.Ctx)error{
return arg.SendString("Hello world \n")
}
func main(){
app := fiber.New()
app.Get("/api",aloha)
log.Fatal(app.Listen(":8000"))
}
|
go mod tidy
go run main.go
curl localhost/api -X GET -I
mkdir database
touch database/database.go
open database.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
package database
import (
"log"
"os"
//"github.com/OzanOcak/api/models"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)
type DbInstance struct {
Db *gorm.DB
}
var Database DbInstance
func ConnectDb() {
db, err := gorm.Open(sqlite.Open("api.db"), &gorm.Config{})
if err != nil {
log.Fatal("Failed to connect to the database! \n", err)
os.Exit(2)
}
log.Println("Connected Successfully to Database")
db.Logger = logger.Default.LogMode(logger.Info)
log.Println("Running Migrations")
//db.AutoMigrate(&models.User{}, &models.Product{}, &models.Order{})
Database = DbInstance{
Db: db,
}
}
|
go get gorm.io/driver/sqlite
go getgorm.io/gorm
go get gorm.io/gorm/logger
mkdir models
touch models/{user.go,product.go,order.go}
order.go
1
2
3
4
5
6
7
8
9
10
11
12
|
package models
import "time"
type Order struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time
ProductRefer int `json:"product_id"`
Product Product `gorm:"foreignKey:ProductRefer"`
UserRefer int `json:"user_id"`
User User `gorm:"foreignKey:UserRefer"`
}
|
product.go
1
2
3
4
5
6
7
8
9
10
|
package models
import "time"
type Product struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time
Name string `json:"name"`
SerialNumber string `json:"serial_number"`
}
|
user.go
1
2
3
4
5
6
7
8
9
10
|
package models
import "time"
type User struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
}
|
now we can migrate models in database.go
1
2
3
|
"github.com/OzanOcak/fiberapi/models"
db.AutoMigrate(&models.User{}, &models.Product{}, &models.Order{})
|
and connect database in main function
click sql tool after download sql vscode plugin, add new connection
with SQLite plugin in vs code , we can see db table within vs code
1
2
|
mkdir routes
touch routes/user.go
|
user.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
package routes
import (
"api/database"
"api/models"
"github.com/gofiber/fiber/v2"
)
type User struct {
ID uint `json:"id"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
}
func CreateResponseUser(userModel models.User) User{
return User{ID: userModel.ID, FirstName: userModel.FirstName, LastName: userModel.LastName}
}
func CreateUser(c *fiber.Ctx) error{
var user models.User
if err := c.BodyParser(&user); err != nil {
return c.Status(404).JSON(err.Error())
}
database.Database.Db.Create(&user)
responseUser := CreateResponseUser(user)
return c.Status(200).JSON(responseUser);
}
|
main.go within setupRoutes and in main connect db
1
|
app.Post("/api/users",routes.CreateUser)
|
curl localhost:8000/users -X POST -d '{"first_name":"john","last_name":"doe"}' -H 'content-type:application/json'
1
2
3
4
5
6
7
8
9
10
11
12
13
|
func GetUsers(c *fiber.Ctx) error{
users := []models.User{}
database.Database.Db.Find(& users)
responseUsers := []User{}
for _,user := range users {
responseUser := CreateResponseUser(user)
responseUsers = append(responseUsers, responseUser)
}
return c.Status(200).JSON(responseUsers)
}
|
1
|
app.Get("/api/users",routes.GetUsers)
|
curl localhost:8000/api/users -X GET
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
func findUser(id int, user *models.User) error{
database.Database.Db.Find(&user, "id=?",id)
if user.ID == 0 {
return errors.New("user does not exist ")
}
return nil
}
func GetUser(c *fiber.Ctx) error{
id, err := c.ParamsInt("id")
var user models.User
if err !=nil {
return c.Status(400).JSON("please enure that :id is an integer")
}
if err := findUser(id, &user); err != nil {
return c.Status(400).JSON(err.Error())
}
responseUser := CreateResponseUser(user)
return c.Status(200).JSON(responseUser)
}
|
and call the function in main function
1
|
app.Get("/api/users/:id",routes.GetUser)
|
curl localhost:8000/users/2 -X GET
routes/user.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
func UpdateUser(c *fiber.Ctx) error {
id, err := c.ParamsInt("id")
var user models.User
if err != nil {
return c.Status(400).JSON("Please ensure that :id is an integer")
}
err = findUser(id, &user)
if err != nil {
return c.Status(400).JSON(err.Error())
}
type UpdateUser struct {
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
}
var updateData UpdateUser
if err := c.BodyParser(&updateData); err != nil {
return c.Status(500).JSON(err.Error())
}
user.FirstName = updateData.FirstName
user.LastName = updateData.LastName
database.Database.Db.Save(&user)
responseUser := CreateResponseUser(user)
return c.Status(200).JSON(responseUser)
}
|
main.go
1
|
app.Put("/users/:id",routes.UpdateUser)
|
curl localhost:8000/users/3 -X PUT -d '{"first_name":"tom","last_name":"cruse"}' -H 'content-type:application/json'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
func DeleteUser(c *fiber.Ctx) error {
id, err := c.ParamsInt("id")
var user models.User
if err != nil {
return c.Status(400).JSON("Please ensure that :id is an integer")
}
err = findUser(id, &user)
if err != nil {
return c.Status(400).JSON(err.Error())
}
if err = database.Database.Db.Delete(&user).Error; err != nil {
return c.Status(404).JSON(err.Error())
}
return c.Status(200).JSON("Successfully deleted User")
}
|
1
|
app.DELETE("/users/:id",routes.DeleteUser)
|
curl localhost:8000/users/3 -X DELETE
routes/product.go
models/product.go
1
2
3
4
5
6
7
8
9
10
|
package models
import "time"
type Product struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time
Name string `json:"name"`
SerialNumber string `json:"serial_number"`
}
|
routes/product.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
package routes
import (
"github.com/OzanOcak/fiberapi/database"
"github.com/OzanOcak/fiberapi/models"
"github.com/gofiber/fiber/v2"
)
type Product struct {
ID uint `json:"id"`
Name string `json:"name"`
SerialNumber string `json:"serial_number"`
}
func CreateResponseProduct(product models.Product) Product {
return Product {ID: product.ID, Name: product.Name, SerialNumber: product.SerialNumber}
}
func CreateProduct(c *fiber.Ctx) error {
var product models.Product
if err := c.BodyParser(&product); err != nil {
return c.Status(400).JSON(err.Error())
}
database.Database.Db.Create(&product)
responseProduct := CreateResponseProduct(product)
return c.Status(200).JSON(responseProduct)
}
|
main.go
1
|
app.Post("/products",routes.CreateProduct)
|
terminal
curl localhost:8000/products -X POST -d '{"serial_number":"0002316","name":"Letrange"}' -H 'content-type:application/json'
product.go
1
2
3
4
5
6
7
8
9
10
11
|
func GetProducts(c *fiber.Ctx) error {
products := []models.Product{}
database.Database.Db.Find(&products)
responseProducts := []Product{}
for _, product := range products {
responseProduct := CreateResponseProduct(product)
responseProducts = append(responseProducts, responseProduct)
}
return c.Status(200).JSON(responseProducts)
}
|
1
|
app.GET("/products",routes.GetProducts)
|
curl localhost:8000/products
1
|
app.Post("/orders",routes.CreateOrder)
|
curl localhost:8000/orders -X POST -d '{"user_id":4,"product_id":1}' -H 'content-type:application/json'
1
|
app.Get("/orders",routes.GetOrders)
|
curl localhost:8000/orders
1
|
app.Get("/orders/:id",routes.GetOrder)
|
curl localhost:8000/orders/1