GO: Restful API для баз данных (GIN+GORM)


สร้าง Project

เริ่มต้นสร้าง Go project ชื่อ tripbooking (project ตัวอย่าง) กันก่อนเลย โดยสร้าง folder ชื่อ tripbooking แล้วเข้าไป folder รันคำสั่งสร้าง project และเปิด vscode ที่ folder นั้น

mkdir tripbooking 
cd tripbooking 
go mod init tripbooking 
code .
Вход в полноэкранный режим Выйти из полноэкранного режима

สร้าง folder ที่จะเอาไว้เก็บไฟล์ต่างๆให้เป็นระเบียบ โดยในที่นี่ขึ้นอยู่กับความเหมาะสม สำหรับที่จะแนะนำให้สร้าง folder ทั้งหมด 4 folder คือ

  • controller = เอาไว้เก็บ restful api controller (path) ต่างๆ
  • сервис = ส่วนประมวลผลต่างๆของ Api
  • модель = struct ของ модель базы данных
  • хранилище = ส่วนที่เชื่อมต่อไปยัง база данных

และสร้างไฟล์อีก 3 ไฟล์คือ

  • config.yaml = ไฟล์การตั้งค่าต่างๆของ project
  • server.go = ไฟล์เริ่มต้นการทำงานของ Server โดย GIN
  • main.go = ไฟล์เริ่มต้นการทำงานของ project

โดยใน main.go ก็จะมี code ของ func main() เริ่มต้น ตามรูป


เพิ่ม libraries ที่เกี่ยวข้องกับ project

go get github.com/gin-gonic/gin
go get gorm.io/gorm
go get gorm.io/driver/mysql
go get github.com/spf13/viper
go install github.com/cosmtrek/air@latest
Вход в полноэкранный режим Выйти из полноэкранного режима

สร้าง Server ด้วย GIN

ที่ไฟล์ server.go สร้าง server ของ restful api ด้วย GIN

package main

import (
    "net/http"
    "os"
    "github.com/gin-gonic/gin"
)

func StartServer() {
    router := gin.Default()
    router.SetTrustedProxies(nil)
    router.GET("/", hello)
    port := os.Getenv("PORT")
    if port == "" {
        port = "8888"
    }
    router.Run(":" + port)
}

func hello(c *gin.Context) {
    c.JSON(http.StatusOK, gin.H{
        "message": "Hello World!!!",
    })
}

Вход в полноэкранный режим Выход из полноэкранного режима

ใน main.go สั่งให้เรียก func StartServer()

package main

func main() {
    StartServer()
}

Вход в полноэкранный режим Выйти из полноэкранного режима

รันโปรแกรมด้วย plugin air เพื่อให้ auto reload เมื่อเราแก้ไข code โดยต้องกำหนดค่าเริ่มต้นให้ก่อน

air init
air
Вход в полноэкранный режим Выйти из полноэкранного режима

ทดสอบเรียก Api อาจใช้ Thunder Client, Talend หรือ Postman ก็ได้


ติดต่อ Database ด้วย GORM

ตั้งค่า dsn ที่จะเชื่อมไปยังฐานข้อมูล MySQL ในไฟล์ config.yaml (อย่าลืมเปิด Server MySQL ตัวอย่างล่ะ หรือ ถ้าเชื่อมไปยัง Server ที่ Online อยู่ก็ได้เลย)

mysql:
  dsn: "username:password@tcp(localhost:3306)/tripbooking?collation=utf8mb4_unicode_ci&parseTime=true"
Вход в полноэкранный режим Выход из полноэкранного режима

จากนั้น สร้างไฟล์ database.go ใน folder repository แล้วเขียนคำสั่งใช้การติดต่อไปยังฐานข้อมูล

package repository


import (
    "github.com/spf13/viper"
    "gorm.io/driver/mysql"
    "gorm.io/gorm"
)

var db *gorm.DB

func NewDatabaseConnection() (*gorm.DB, error) {
    if db == nil {
        viper.SetConfigName("config")
        viper.AddConfigPath(".")
        err := viper.ReadInConfig()
        if err != nil {
            panic(err)
        }
        dsn := viper.GetString("mysql.dsn")
        dialector := mysql.Open(dsn)
        db, err = gorm.Open(dialector)
        if err != nil {
            return nil, err
        }
    }
    return db, nil
}
Вход в полноэкранный режим Выход из полноэкранного режима

ซึ่งได้จะ func NewDatabaseConnection() ไว้ใช้ในการติดต่อไปยังฐานข้อมูลที่เราได้ตั้งค่าไว้


ติดต่อไปดึงข้อมูลจากฐานข้อมูล (Table) ต้องมี Model (Entity) ที่เป็นตัวแทนของ Table นั้นๆ ตัวอย่างเช่น จะดึงข้อมูลจาก Table destination ก็ต้องสร้าง Model Destination ขี้นมาก่อน

สร้างไฟล์ destinationModel.go ใน folder model และเขียน model ตามโครงสร้างของ table destination

package model

type Destination struct {
    ID   uint   `gorm:"column:idx;primaryKey"`
    Zone string `gorm:"column:zone;size:255"`
}

func (Destination) TableName() string {
    return "destination"
}
Вход в полноэкранный режим Выход из полноэкранного режима

ในกรณีที่ไม่อยากเขียน struct ของ model เอง ให้ใช้วิธีนี้คือ

  • เข้า phpmyadmin แล้วรันคำสั่ง (destination คือชื่อ table ที่ต้องการ) โดยเลือกการแสดงผลตรง option ให้เป็น แบบ Full Text
SHOW CREATE TABLE destination
Вход в полноэкранный режим Выход из полноэкранного режима

  • จะได้คำสั่งสร้าง Table ออกมา ให้ copy คำสั่ง Create นั้นไว้ แล้วเข้าที่เวบ https://sql2gorm.mccode.info
  • วางคำสั่ง sql ลงไป เวบจะสร้าง struct ของ model ให้ตามรูป (เลือก json tag เป็น include ด้วยนะ ถ้าจะใช้เป็น DTO รับข้อมูลรูปแบบ json)


สร้าง Repositoy ที่เป็นตัวเชื่อมไปยังฐานข้อมูล โดยในการเขียนนี้ เราจะสร้างให้อยู่ในรูปแบบ Interface (ถ้ายังไม่รู้จักจะงงๆหน่อยนะ) เพื่อให้สะดวกต่อการใช้งาน อาจดูยุ่งยาก แต่มันดีในอนาคตเวลาโปรแกรมมันขยายและซับซ้อนขึ้น

สร้างไฟล์ destinationRepository.go ไว้ใน folder repository และเขียนให้ไปดึงข้อมูลของ table destination มา (FindAll) โดยมี pattern ของการเขียนดังตัวอย่าง

package repository

import (
    "tripbooking/model"

    "gorm.io/gorm"
)

// repository struct (<name>DB)
type destinationRepo struct {
    db *gorm.DB
}

// repository contructor (New<name>Repository)
func NewDestinationRepository() DestinationRepository {
    db, err := NewDatabaseConnection()
    if err != nil {
        return nil
    }
    return destinationRepo{db: db}
}

// repository interface (<name>Repository)
type DestinationRepository interface {
    FindAll() (*[]model.Destination, error)
}

// implement functions conformed interface
func (d destinationRepo) FindAll() (*[]model.Destination, error) {
    destinations := []model.Destination{}
    result := d.db.Find(&destinations)
    if result.Error != nil {
        return nil, result.Error
    }
    return &destinations, nil
}
Вход в полноэкранный режим Выход из полноэкранного режима

เมื่อสร้าง Repository เสร็จแล้ว ขี้นต่อไปคือการสร้าง Service เพื่อใช้ประมวลผลต่างๆ

เราจะไม่ประมวลใน repository และ controller ถ้าไม่จำเป็น

สร้างไฟล์ destinationService.go ใน folder service เพื่อใช้เขียนการประมวลผลในรูปแบบของ service ซึ่งจะมี pattern การเขียนแบบ interface เหมือน repository

package service

import (
    "tripbooking/model"
    "tripbooking/repository"
)

// service struct (<name>Serv)
type destinationServ struct{}

// service contructor (New<name>Service)
func NewDestinationService() DestinationService {
    return destinationServ{}
}

// create repositories
var destinationRepo = repository.NewDestinationRepository()

// service interface (<name>Service)
type DestinationService interface {
    GetAllDestinations() (*[]model.Destination, error)
}

func (d destinationServ) GetAllDestinations() (*[]model.Destination, error) {

    destinations, err := destinationRepo.FindAll()
    if err != nil {
        return nil, err
    }
    return destinations, nil
}
Вход в полноэкранный режим Выйти из полноэкранного режима

เมื่อได้ส่วนประมวลผลแล้ว ต่อไปจะทำการสร้าง controller เพื่อให้ user สามารถเรียกใช้งาน api เราได้ โดยสร้างไฟล์ destinationController.go ใน folder controller แล้วเขียนเรียกใช้งาน service ดังตัวอย่าง

package controller

import (
    "net/http"
    "tripbooking/service"

    "github.com/gin-gonic/gin"
)

// create services
var destinationServ = service.NewDestinationService()

// Initiate Controller
func NewDestinationController(router *gin.Engine) {
    r := router.Group("/destination")
    {
        r.GET("", findAll)
    }
}

// Implement Controller
func findAll(c *gin.Context) {
    destinations, err := destinationServ.GetAllDestinations()
    if err != nil {
        c.JSON(http.StatusBadRequest, gin.H{
            "error": err,
        })
    }
    c.JSON(http.StatusOK, destinations)
}
Вход в полноэкранный режим Выход из полноэкранного режима

เมื่อได้ controller แล้ว ต่อไป จะเป็นการผูก Controller เข้าไปยัง Server ที่เราสร้าง

มาที่ไฟล์ server.go และเพิ่ม (Register) Controller ของเราเข้าไป ตาม code ตัวอย่าง

func StartServer() {
    router := gin.Default()
    router.SetTrustedProxies(nil)
    router.GET("/", hello)
    port := os.Getenv("PORT")
    if port == "" {
        port = "8888"
    }

    // **** Register controllers
    controller.NewDestinationController(router)

    router.Run(":" + port)
}
Вход в полноэкранный режим Выйти из полноэкранного режима

จากนั้นทดลองเรียก api โดยใช้ /destination จะได้ผลลัพธ์ตามตัวอย่าง


เสร็จสิ้นการเริ่มต้น GO Project ในการสร้าง Restful api เชื่อมต่อไปยัง MySQL ด้วย GIN และ GORM

Оцените статью
devanswers.ru
Добавить комментарий