This page looks best with JavaScript enabled

Viết API sử dụng Fiber Framework + Postgresql trong Golang

 ·  ☕ 5 phút đọc · 👀... views

Fiber là gì?

Fiber là một khung web lấy cảm hứng từ Express Web Framewok của NodeJs được xây dựng trên Fasthttp, công cụ HTTP nhanh nhất dành cho Go.

Được thiết kế để dễ dàng mọi thứ nhằm phát triển nhanh chóng mà không cần lưu ý đến hiệu suất và phân bổ bộ nhớ.

Các tính năng của Fiber Framework

  • Robust routing / Định tuyến mạnh mẽ
  • Serve static files / Cung cấp các tệp tĩnh
  • Extreme performance . Hiệu suất cực cao
  • Low memory footprint / Sử dụng bộ nhớ thấp
  • API endpoints / Điểm cuối API
  • Middleware & Next support
  • Rapid server-side programming / Lập trình phía máy chủ nhanh chóng
  • Template engines / Công cụ mẫu
  • Hỗ trợ WebSocket
  • Rate Limiter / Giới hạn tỷ lệ
  • Được dịch sang 15 ngôn ngữ
  • Và nhiều hơn nữa…

Set up the Project

1.Tạo thư mục

1
2
3
$ mkdir Gofiber

$ cd Gofiber
  1. Khởi tạo project
1
$ go mod init github.com/<your GitHub username>/Gofiber
  1. Tạo các thư mục cần thiết
1
$ mkdir service storage models

Install the Required Libraries

1.Cài đặt Gofiber

1
$ go get -u github.com/gofiber/fiber/v2
  1. Cài đặt Gorm
1
$ go get -u gorm.io/gorm
  1. Install Gorm Postgres driver.
1
$ go get -u gorm.io/driver/postgres
  1. Install Godotenv, used for loading environment variables.
1
$ go get github.com/joho/godotenv
  1. Install Validator.
1
$ go get github.com/go-playground/validator/v10

Cài đặt database

  1. Chuyển sang user postgres để thao tác
$ sudo -iu postgres psql
  1. Khởi tạo database
CREATE DATABASE gofiber;
  1. Exit
\q
  1. Khởi tạo file .env và paste cấu hình sau
DB_HOST=localhost

DB_PORT=5432

DB_USER=yourusername

DB_PASS=yourpassword

DB_NAME=gofiber

DB_SSLMODE=disable
  1. Tạo file postgres.go và paste đoạn code sau
package storage



import (

    "fmt"

    "gorm.io/driver/postgres"

    "gorm.io/gorm"

)



type Config struct {

    Host     string

    Port     string

    Password string

    User     string

    DBName   string

    SSLMode  string

}



func NewConnection(config *Config) (*gorm.DB, error) {

    dsn := fmt.Sprintf(

        "host=%s port=%s user=%s password=%s dbname=%s sslmode=%s",

        config.Host, config.Port, config.User, config.Password, config.DBName, config.SSLMode,

    )

    db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})

    if err != nil {

        return db, err
    }
    return db, nil
}

Tạo model

Chúng ta sẽ tạo 1 folder models và tạo 1 file mới là books.go

package models
import "gorm.io/gorm"
type Books struct {
    ID        uint    `gorm:"primary key;autoIncrement" json:"id"`

    Author    *string `json:"author"`

    Title     *string `json:"title"`

    Publisher *string `json:"publisher"`
}
func MigrateBooks(db *gorm.DB) error {
    err := db.AutoMigrate(&Books{})
    return err
}

Tạo service

Mục đích để chúng ta xây dựng 1 cầu nối đứng giữa để kết nối tới Database

type Book struct {

Author    string `json:"author" validate:"required"`

Title     string `json:"title" validate:"required"`

Publisher string `json:"publisher" validate:"required"`

}

type Repository struct {

DB *gorm.DB

}

Ở đây mình đã tạo một cấu trúc để người dùng truyền lên.validate:required là thẻ sẽ được sử dụng để đảm bảo người dùng không bỏ qua bất kỳ trường nào khi tạo giá trị.

Sau bước này mình sẽ tạo các hàm thực hiện các chức năng như sau:

  • Create books
  • Update book by id
  • Delete book by id
  • Get all books
  • Get books by id

Create Books

func (r *Repository) CreateBook(context *fiber.Ctx) error {

    book := Book{}



    err := context.BodyParser(&book)

    if err != nil {

        context.Status(http.StatusUnprocessableEntity).JSON(

            &fiber.Map{"message": "request failed"})

        return err

    }

    validator := validator.New()

    err = validator.Struct(Book{})



    if err != nil {

        context.Status(http.StatusUnprocessableEntity).JSON(

            &fiber.Map{"message": err},

        )

        return err

    }



    err = r.DB.Create(&book).Error



    if err != nil {

        context.Status(http.StatusBadRequest).JSON(

            &fiber.Map{"message": "could not create book"})

        return err

    }



    context.Status(http.StatusOK).JSON(&fiber.Map{

        "message": "book has been successfully added",

    })

    return nil

}

Update Books by ID

func (r *Repository) UpdateBook(context *fiber.Ctx) error {

    id := context.Params("id")

    if id == "" {

        context.Status(http.StatusInternalServerError).JSON(&fiber.Map{

            "message": "id cannot be empty",

        })

        return nil

    }



    bookModel := &models.Books{}

    book := Book{}





err := context.BodyParser(&book)

if err != nil {

    context.Status(http.StatusUnprocessableEntity).JSON(

        &fiber.Map{"message": "request failed"})

    return err

}



err = r.DB.Model(bookModel).Where("id = ?", id).Updates(book).Error

if err != nil {

    context.Status(http.StatusBadRequest).JSON(&fiber.Map{

        "message": "could not update book",

    })

    return err

}



    context.Status(http.StatusOK).JSON(&fiber.Map{

        "message": "book has been successfully updated",

    })

    return nil



}

Delete Book by ID

func (r *Repository) DeleteBook(context *fiber.Ctx) error {

    bookModel := &models.Books{}



    id := context.Params("id")

    if id == "" {

        context.Status(http.StatusInternalServerError).JSON(&fiber.Map{

            "message": "id cannot be empty",

        })

        return nil

    }



    err := r.DB.Delete(bookModel, id)



    if err.Error != nil {

        context.Status(http.StatusBadRequest).JSON(&fiber.Map{

            "message": "could not delete book",

        })

        return err.Error

    }



    context.Status(http.StatusOK).JSON(&fiber.Map{

        "message": "book has been successfully deleted",

    })

    return nil

Get All Books

func (r *Repository) GetBooks(context *fiber.Ctx) error {

    bookModels := &[]models.Books{}



    err := r.DB.Find(bookModels).Error

    if err != nil {

        context.Status(http.StatusBadRequest).JSON(

            &fiber.Map{"message": "could not get books"})

        return err

    }



    context.Status(http.StatusOK).JSON(&fiber.Map{

        "message": "books gotten successfully",

        "data":    bookModels,

    })

    return nil



}

Get Books by ID

func (r *Repository) GetBookByID(context *fiber.Ctx) error {

id := context.Params("id")

bookModel := &models.Books{}

if id == "" {

context.Status(http.StatusInternalServerError).JSON(&fiber.Map{

"message": "id cannot be empty",

})

return nil

}



err := r.DB.Where("id = ?", id).First(bookModel).Error

if err != nil {

context.Status(http.StatusBadRequest).JSON(

&fiber.Map{"message": "could not get book"})

return err

}



context.Status(http.StatusOK).JSON(&fiber.Map{

"message": "books id gotten successfully",

"data":    bookModel,

})

return nil

}

Cài đặt Routes

func (r *Repository) SetupRoutes(app *fiber.App) {

    api := app.Group("/api")

    api.Post("/create_books", r.CreateBook)

    api.Delete("/delete_book/:id", r.DeleteBook)

    api.Put("/update_book/:id", r.UpdateBook)

    api.Get("/get_books/:id", r.GetBookByID)

    api.Get("/books", r.GetBooks)

}

Tạo main function

func main() {

    err := godotenv.Load(".env")

    if err != nil {

        log.Fatal(err)

    }



    config := &storage.Config{

        Host:     os.Getenv("DB_HOST"),

        Port:     os.Getenv("DB_PORT"),

        Password: os.Getenv("DB_PASS"),

        User:     os.Getenv("DB_USER"),

        SSLMode:  os.Getenv("DB_SSLMODE"),

        DBName:   os.Getenv("DB_NAME"),

    }

    db, err := storage.NewConnection(config)

    if err != nil {

        log.Fatal("could not load database")

    }



    err = models.MigrateBooks(db)

    if err != nil {

        log.Fatal("could not migrate db")

    }



    r := &service.Repository{

        DB: db,

    }

    app := fiber.New()

    r.SetupRoutes(app)



    app.Listen(":8080")



}

Các bạn có tham khảo nhiều ví dụ, ứng dụng của Fiber Web Framework

Chia sẻ
Support the author with

Hùng Phạm
Viết bởi
Hùng Phạm
Web/Mobile Developer