สร้าง Go Fiber RESTful API

หากคุณสงสัยว่าจะเริ่มต้นพัฒนา API ใน Go ได้อย่างไร หรือคุณเพิ่งเข้าใจพื้นฐานของ Go และต้องการเริ่มต้นกับการพัฒนาจริง นี่จะเป็นจุดเริ่มต้นที่ดี

Go Fiber เป็นเว็บเฟรมเวิร์กแบบ Go-based ใหม่ที่ได้รับความนิยมอย่างมากจากชุมชนการเขียนโปรแกรม พื้นที่เก็บข้อมูลสำหรับเฟรมเวิร์กอยู่ในหน้า GitHub Trending สำหรับการเขียนโปรแกรมภาษา Go อย่างสม่ำเสมอ และด้วยเหตุนี้ เราจึงต้องลองสร้าง REST API อย่างง่าย

Rest (Representational state transfer) – เป็นรูปแบบสถาปัตยกรรมซอฟต์แวร์ (architecture) ที่ใช้ประโยชน์จากเทคโนโลยี Web Protocol เพื่อใช้ในการสร้าง Web Service

API ย่อมาจาก Application Programming Interface คือ ช่องทางการเชื่อมต่อ ,ช่องทางหนึ่งที่จะเชื่อมต่อกับเว็บไซต์ผู้ให้บริการ API จากที่อื่น เป็นตัวกลางที่ทำให้โปรแกรมประยุกต์เชื่อมต่อกับโปรแกรมประยุกต์อื่น หรือเชื่ิอมการทำงานเข้ากับระบบปฏิบัติการ 


ดังนั้น ในบทความนี้ เราจะพูดถึงวิธีที่คุณสามารถเริ่มต้นสร้างระบบ REST API ของคุณเองด้วยภาษา Go โดยใช้ Go fiber web framework นี้!

ออกแบบ RESTful API


ก่อนจะลงมือสร้าง API ก็ต้องออกแบบ API กันก่อน ในวันนี้เราจะสร้าง API พื้นฐานเบื้องต้น ดังนี้

POST /todos สร้างข้อมูลใหม่
GET /todos/1 ขอดูข้อมูลไอดีที่ 1
PUT /todos/1 แก้ไขข้อมูลไอดีที่ 1
DELETE /todos/3 ลบข้อมูลไอดีที่ 3


ข้อกำหนดเบื้องต้น


ในการปฏิบัติตามบทความนี้ คุณต้องมีความรู้เกี่ยวกับ พื้นฐานภาษา Go

ซึ่งรวมถึง:

  • ติดตั้ง Go บนคอมพิวเตอร์ของคุณแล้ว เรียกใช้ go version คำสั่งเพื่อตรวจสอบการติดตั้ง Go
  • สามารถตั้งค่าโปรแกรม Go พื้นฐานได้
  • เรียกใช้และสร้างแอปพลิเคชัน Go รวมทั้งทำความเข้าใจวิธีเขียนโค้ด Go


ขั้นตอนการทำ RESTful API


สร้างโฟลเดอร์โมดูลชื่อ todolist และ สร้างไฟล์ go.mod

go mod init todolist


สร้างไฟล์ main.go


เขียนโค้ดดังนี้

package main

import "github.com/gofiber/fiber/v2"

func main() {
  app := fiber.New()

  app.Get("/", func(c *fiber.Ctx) error {
    return c.SendString("Hello, World!")
  })

  app.Listen(":3000")
}


ติดตั้ง Go Fiber


Go Fiber เป็นเว็บเฟรมเวิร์กที่สร้างขึ้นบน HTTP ที่รวดเร็ว สามารถใช้ในการจัดการการดำเนินการต่างๆ เช่น การกำหนดเส้นทาง/ปลายทาง มิดเดิลแวร์ คำขอของเซิร์ฟเวอร์


ติดตั้ง Go Fiber ตามลิงค์ https://docs.gofiber.io/ ภายในโฟลเดอร์โมดูล todolist ใช้คำสั่ง

go get github.com/gofiber/fiber/v2


ติดตั้ง GORM


GORM เป็น Go ORM ช่วยให้เรา Map ระหว่างโครงสร้างของ Column ใน Table ของ Database กับ Field ของ Struct ใน Go ได้

ติดตั้ง GORM ตามลิงค์ https://gorm.io/docs/ ภายในโฟลเดอร์โมดูล todolist ใช้คำสั่ง

go get -u gorm.io/gorm


ติดตั้ง PostgreSQL



เริ่มเเรกดาวน์โหลด PostgreSQL มาก่อน สามารถดาวน์โหลดและติดตั้งโปรแกรมที่ : https://www.enterprisedb.com/downloads/postgres-postgresql-downloads ตั้งชื่อ dbname , password และ port ตามต้องการ (ในบทความ dbname คือ goTodo , password คือ lungmaker และ port คือ 54321)


> ลิงค์การติดตั้ง PostgreSQL

PostgreSQL เป็นระบบจัดการฐานข้อมูลโอเพ่นซอร์สระดับองค์กรที่ทันสมัย ที่พัฒนาโดย PostgreSQL Global Development Group เป็นระบบฐานข้อมูล SQL (Structured Query Language) เชิงวัตถุสัมพันธ์ที่มีประสิทธิภาพและขยายได้สูง

ตัวอย่างการใช้งาน https://gorm.io/docs/connecting_to_the_database.html#Customize-Driver-1

ที่โฟลเดอร์โมดูล todolist ใช้คำสั่ง

go get -u gorm.io/driver/postgres


Create Todo Gorm Model (สร้างการเชื่อมต่อฐานข้อมูล)


สร้างโฟลเดอร์ใหม่ชื่อว่า database และสร้างไฟล์ชื่อ database.go เขียนโค้ดดังนี้

package database

import (
	_ "gorm.io/driver/postgres"
	"gorm.io/gorm"
)

var (
	DBConn *gorm.DB
)


Setup Gorm and Fiber Routes (ตั้งค่าการ Gorm และ เส้นทาง)


สร้างโฟลเดอร์ใหม่ที่ชื่อว่า models และสร้างไฟล์ชื่อ todo.go


เขียนโค้ดดังนี้

package models

import (
	"todolist/database"
	"github.com/gofiber/fiber/v2"

)

type Todo struct {
	ID 		  uint 	  `gorm:"primarykey" json:"id"`
	Title 	  string  `json:"title"`
	Completed bool 	  `json:"completed"`

}

func GetTodos(c *fiber.Ctx) error {
	db := database.DBConn
	var todos []Todo
	db.Find(&todos)
	return c.JSON(&todos)
}


แก้ไขโค้ดที่ไฟล์ main.go 


แก้ไขโค้ดที่ไฟล์ main.go ตามโค้ดด้านล่าง (ชื่อ dbname , password และ port ให้แก้ไขตามที่เรากำหนดไว้ในขั้นตอนติดตั้ง PostgreSQL)

package main

import (
	"github.com/gofiber/fiber/v2"
	"todolist/models"
	"todolist/database"
	"gorm.io/driver/postgres"
	"gorm.io/gorm"
	"fmt"
)

func helloWord(c *fiber.Ctx) error {
	return c.SendString("Hello world")
  }

func initDatabase() {
	var err error
	dsn := "host=localhost user=postgres password=lungmaker dbname=goTodo port=54321"
	database.DBConn, err = gorm.Open(postgres.Open(dsn), &gorm.Config{})
	if err != nil {
		panic("Failed to connect to database")
	}
	fmt.Println("Database connected!")
	database.DBConn.AutoMigrate(&models.Todo{})
	fmt.Println("Migrated DB")
}

func setupRoutes(app *fiber.App) {
	app.Get("/todos", models.GetTodos)
}

func main() {
  app := fiber.New()
  initDatabase()
  app.Get("/", helloWord)
  setupRoutes(app)
  app.Listen(":8000")
}

แอปพร้อมแล้ว และตอนนี้เราสามารถทดสอบได้โดยใช้คำสั่งต่อไปนี้:

go run main.go

หากคุณไปที่เว็บบราวเซอร์ ป้อน URL http://localhost:8000/ คุณจะเห็นว่า Hello, World! อยู่บนหน้าจอของคุณ

แต่ถ้าหากคุณป้อน URL http://localhost:8000/todos แล้วขึ้นแบบภาพด้านล่าง แสดงว่าขั้นตอนนี้สำเร็จแล้ว

เปิด pgAdmin 4 ของ PostgreSQL จะพบไฟล์ฐานข้อมูลที่เราสร้างขึ้น


และตารางข้อมูลที่เราสร้างขึ้นจากการเขียนโค้ด ด้านล่าง


Create Todos Request (เพิ่มข้อมูล)


ที่ไฟล์ todo.go เพิ่มโค้ดดังนี้

func CreateTodo(c *fiber.Ctx) error {
	db := database.DBConn
	todo := new(Todo)
	err := c.BodyParser(todo)
	if err != nil {
		return c.Status(500).JSON(fiber.Map{"status": "error", "massage": "Check your input", "data": err})
	}
	err = db.Create(&todo).Error
	if err != nil {
		return c.Status(500).JSON(fiber.Map{"status": "error", "massage": "Could not create todo", "data": err})
	}
	return c.JSON(&todo)
}


ที่ไฟล์ main.go เพิ่มโค้ดดังนี้

app.Post("/todos", models.CreateTodo)


ทดสอบการทำงาน


ติดตั้งโปรแกรม Insomnia


Insomnia เป็นโปรแกรมที่ขาดไม่ได้เลยสำหรับการทำ API , Insomnia คือ โปรแกรมเอาไว้สำหรับทดลองยิง request ไปยัง Service หรือเว็บไซต์ต่างๆ


Download ได้ที่  https://insomnia.rest/download

การใช้งานเบื้องต้น https://www.youtube.com/watch?v=WhCRjd043gE

ทดสอบโค้ดด้านล่าง เลือก POST ด้านล่างเลือกเป็น JSON แล้วป้อน URL http://localhost:8000/todos กดปุ่ม Send

POST จะเป็นการส่งข้อมูลกลับไปหาแหล่งข้อมูล โดยมันจะส่งข้อมูลชุดหนึ่งแนบไปด้วย อย่างในกรณีตัวอย่างนี้คือจะส่งข้อมูลสำหรับให้สร้าง title ใหม่ไปด้วยนั่นเอง

JSON นั้นมีชื่อเต็มๆว่า JavaScript Object Notation เป็นข้อมูลรูปแบบ text ที่มีรูปแบบที่จะเก็บข้อมูลแบบ key, value โดยการเขียนข้อมูลชนิด JSON มีรูปแบบคือ ชื่อฟิลด์ครอบด้วยเครื่องหมาย “ (double quote), เครื่องหมาย : (colon), value แล้วครอบทั้งหมดด้วยเครื่องหมายปีกกา

{
	"title": "do something else",
	"compleled": false
}


คุณจะเห็นข้อมูลที่ 1 เพิ่มที่ช่อง Preview ด้านขวา


และ ทดสอบโค้ดด้านล่าง -> Send

{
	"title": "go developers thailand",
	"compleled": false
}


คุณจะเห็นข้อมูลที่ 2 เพิ่มที่ช่อง Preview ด้านขวา


เข้าไปดูที่ฐานข้อมูล จะพบข้อมูลที่เพิ่มเข้าไป


Get Todos By Id (คิวรี่สตริง)


ที่ไฟล์ todo.go เพิ่มโค้ดดังนี้

func GetTodoById(c *fiber.Ctx) error{
	id := c.Params("id")
	db := database.DBConn
	var todo Todo
	err := db.Find(&todo, id).Error 
	if err != nil {
		return c.Status(404).JSON(fiber.Map{"status": "error", "massage": "Could not find todo", "data": err})
	}

	return c.JSON(&todo)
}



ที่ไฟล์ main.go เพิ่มโค้ดดังนี้

app.Get("/todos/:id", models.GetTodoById)



ทดสอบการทำงาน


ไปที่โปรแกรม Insomnia เลือก GET ด้านล่างเลือกเป็น Body แล้วป้อน URL http://localhost:8000/todos/1 กดปุ่ม Send คุณจะเห็นข้อมูลที่ 1 จากการ คิวรี่สตริงใน URL ที่ช่อง Preview ด้านขวา

GET จะเป็นการส่ง URL ร้องขอข้อมูลไปตรงๆ หรือการส่งไปพร้อมกับคิวรี่สตริงใน URL อย่างในกรณีตัวอย่างนี้คือจะส่งข้อมูลสำหรับ คิวรี่สตริง 1 ไปด้วยนั่นเอง



ที่เว็บบราวเซอร์ 


ป้อน URL http://localhost:8000/todos/2 กดปุ่ม Send คุณจะเห็นข้อมูลที่ 2 จากการ คิวรี่สตริงใน URL ที่ช่อง Preview ด้านขวา


ที่เว็บบราวเซอร์ 


Update Todos (แก้ไขข้อมูล)


ที่ไฟล์ todo.go เพิ่มโค้ดดังนี้

func UpdateTodo(c *fiber.Ctx) error {
	type UpdateTodo struct {
		Title 	  string  `json:"title"`
		Completed bool 	  `json:"completed"`
	}
	id := c.Params("id")
	db := database.DBConn
	var todo Todo
	err := db.Find(&todo, id).Error 
	if err != nil {
		return c.Status(404).JSON(fiber.Map{"status": "error", "massage": "Could not find todo", "data": err})
	}

	var updatedTodo UpdateTodo
	err = c.BodyParser(&updatedTodo)

	if err != nil {
		return c.Status(500).JSON(fiber.Map{"status": "error", "massage": "Review your input", "data": err})
	}

	todo.Title = updatedTodo.Title
	todo.Completed = updatedTodo.Completed
	db.Save(&todo)
	return c.JSON(&todo)
}


ที่ไฟล์ main.go เพิ่มโค้ดดังนี้

app.Put("/todos/:id", models.UpdateTodo)


ทดสอบการทำงาน

ไปที่โปรแกรม Insomnia เลือก PUT ด้านล่างเลือกเป็น JSON แล้วป้อน URL http://localhost:8000/todos/1

PUT นั้นลักษณะการทำงานโดยรวมจะคล้ายกับ POST ต่างกันที่ว่า PUT จะส่งข้อมูลไปยังตำแหน่งที่ยังไม่มีอยู่  และสร้างข้อมูลขึ้นในตำแหน่งนั้นๆ  หรือเพื่อไปอัพเดทข้อมูลในตำแหน่งที่มีอยู่แล้ว

การส่ง PUT ไปที่นี้คือจะได้ผลลัพธ์ 2 กรณีคือ
ถ้ายังไม่มี id 1 ให้ทำการสร้าง id ใหม่ด้วย id 1 ด้วยข้อมูลที่ส่งไป
ถ้ามี id 1 อยู่แล้ว ให้อัพเดทข้อมูลด้วยข้อมูลที่ส่งไป

{
	"id":  1,
	"title": "Golang developer",
	"compleled": true
}


กดปุ่ม Send



คุณจะเห็นข้อมูล title ที่ช่อง Preview ด้านขวา เปลี่ยนไปตามค่าที่เรากำหนดใหม่


ที่เว็บบราวเซอร์ 


Delete Todos (ลบข้อมูล)


ที่ไฟล์ todo.go เพิ่มโค้ดดังนี้

func DeleteTodo(c *fiber.Ctx) error {
	id := c.Params("id")
	db := database.DBConn
	var todo Todo
	err := db.Find(&todo, id).Error 
	if err != nil {
		return c.Status(404).JSON(fiber.Map{"status": "error", "massage": "Could not find todo", "data": err})
	}

	db.Delete(&todo)

	return c.SendStatus(200)
}


ที่ไฟล์ main.go เพิ่มโค้ดดังนี้

app.Delete("/todos/:id", models.DeleteTodo)


ทดสอบการทำงาน

ไปที่โปรแกรม Insomnia เลือก GET ด้านล่างเลือกเป็น Body แล้วป้อน URL http://localhost:8000/todos/ กดปุ่ม Send คุณจะเห็นข้อมูล id ที่ 1 ถึง id 3 ที่ช่อง Preview ด้านขวา ซึ่ง id ที่ 3 ที่มีการเพิ่มใหม่เข้าไป มี ข้อมูลซ้ำกับ id ที่ 2 จึงต้องการลบออกไป


เลือก DELETE ด้านล่างเลือกเป็น Body แล้วป้อน URL http://localhost:8000/todos/3 กดปุ่ม Send

DELETE จะเป็นการสั่งลบข้อมูลที่มีอยู่แล้ว เช่น เพื่อสั่งให้ลบข้อมูล id 3


ทดสอบ เลือก GET แล้วป้อน URL http://localhost:8000/todos/ กดปุ่ม Send จะเห็นว่า ข้อมูล id ที่ 3 ถูกลบออกไปแล้ว


Enable CORS


การใช้ CORS https://docs.gofiber.io/api/middleware/cors เพื่อ อณุญาติให้ Port ของ back-end และ front-end ที่ต่างกันสามารถทำงานร่วมกันได้

มีขั้นตอนดังนี้

import เพิ่มเข้าไปที่ไฟล์ main.go

"github.com/gofiber/fiber/v2/middleware/cors"


ที่ ฟังค์ชัน main เพิ่มโค้ดดังนี้

app.Use(cors.New())



ทดสอบการทำงาน ถ้าสามารถทำงานได้ app ก็พร้อมสำหรับในการทำงานกับ front-end ที่ต่างกันต่อไป

credit : https://www.udemy.com/course/build-a-todolist-with-go-golang-fiber-and-react/

Leave a Reply

Your email address will not be published. Required fields are marked *