router และ handlers ภาษา GO


ความหมายของ back-end สำหรับ developer จะเรียกกันสั้น ๆ ว่า หลังบ้าน หรือระบบจัดการเว็บไซต์ เช่น จัดการฐานข้อมูล โครงสร้างเว็บไซต์ การเขียนโค้ดควบคุม JSON เป็นต้น ความสำคัญของ back-end ส่วนของ back-end มีความสำคัญเป็นอย่างยิ่ง ไม่ว่าจะเป็นการรักษาความปลอดภัยของข้อมูล ทั้ง username password ข้อมูลเว็บไซต์ต่างๆ หาก backend มีการ update ก็ต้องทำการ backup ข้อมูลเดิมเก็บไว้ และตรวจสอบให้ดีก่อนทำการ update รวมไปถึงการทำงานของเว็บไซต์ ความเร็วในการแสดงผล

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


ข้อกำหนดสำหรับบทความนี้คือ คุณต้องติดตั้ง Go บนคอมพิวเตอร์ของคุณตามบทความ ติดตั้ง Go และ ทดสอบ Hello World และ คุณคุ้นเคยกับรูปแบบและโครงสร้างของมัน มาก่อน

สร้างโปรเจคใหม่


สร้างโปรเจคใหม่ โดยไปที่ File -> Open Folder -> New Folder ตั้งชื่อเป็น backend-app

สร้างโฟลเดอร์ cmd แล้วสร้างโฟลเดอร์ api ภายในโฟลเดอร์ cmd


Go Modules


Go Modules คือสิ่งที่สร้างขึ้นมาเพื่อจัดการ packages ต่างๆ สามารถกำหนดเวอร์ชั่นได้และมีการจัดการที่มีประสิทธิภาพมากขึ้น

สร้างไฟล์ Go Modules ด้วยคำสั่ง

go mod init backend


Flag


วิธีการ ที่จะสามารถทำให้เราส่งค่าจากคำสั่ง Command Line เข้าไปใช้ภายในโปรแกรมเราได้ ในภาษา Go เรียกสิ่งนี้ว่า Command-Line Flag โดย Go จะใช้ Flag ในการทำ operation ต่างๆ โดยเฉพาะ arguments ที่จะส่งไปหาระบบปฏิบัติการ

วิธีการใช้งานหลัก ๆ คือ
flag . ประเภทค่า ( ชื่อคีย์ , ค่าเริ่มต้น , คำอธิบาย )
flag.Parse() //นำค่าจาก command มาใช้ใน flag


สร้างไฟล์ main.go ในโฟลเดอร์ api แล้วเขียนโค้ดดังนี้

package main

import (
	"flag"
	"fmt"
)

const version = "1.0.0"

type config struct {
	port int
	env  string
}

func main() {
	var cfg config

	flag.IntVar(&cfg.port, "port", 4000, "Server port to listen on")
	flag.StringVar(&cfg.env, "env", "development", "Application environment (development|production")
	flag.Parse()

	fmt.Println("Running")
}


ทดสอบการทำงานด้วยคำสั่ง

go run cmd/api/main.go


ที่ TERMINAL แสดงข้อความ Running แสดงว่าไม่พบปัญหาใดๆ


Router


การตั้งค่ากำหนด router ประกอบด้วยส่วน logical ที่เรียกว่า router หรือ เส้นทาง เป็นที่อยู่ของ respond ในแอป ในการตั้งค่า router ให้เรียกใช้เมธอด HandleFunc() บนอินสแตนซ์ http และกำหนด router เพื่อตอบสนองต่อคำขอ ในตัวอย่างเป็น /status

package main

import (
	"flag"
	"fmt"
	"log"
	"net/http"
)

const version = "1.0.0"

type config struct {
	port int
	env  string
}

func main() {
	var cfg config

	flag.IntVar(&cfg.port, "port", 4000, "Server port to listen on")
	flag.StringVar(&cfg.env, "env", "development", "Application environment (development|production")
	flag.Parse()

	fmt.Println("Running")

	http.HandleFunc("/status", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprint(w, "status")
	})	

	err := http.ListenAndServe(fmt.Sprintf(":%d", cfg.port), nil)
	if err != nil {
		log.Println(err)
	}
}


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


ไปที่เว็บเบราว์เซอร์ป้อน url เป็น http://localhost:4000/status ที่เพจจะแสดงข้อความ status


JSON


JSON ( JavaScript Object Notation ) เป็นหนึ่งในรูปแบบการแลกเปลี่ยนข้อมูลที่ได้รับความนิยมมากที่สุดบนเว็บ เป็นรูปแบบที่เข้ารหัสข้อความซึ่งหมายความว่าข้อมูล JSON เป็นสตริงอักขระที่เขียนในรูปแบบ JSON

package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"net/http"
)

const version = "1.0.0"

type config struct {
	port int
	env  string
}

type AppStatus struct {
	Status      string `json:"status"`
	Environment string `json:"environment"`
	Version     string `json:"version"`
}

func main() {
	var cfg config

	flag.IntVar(&cfg.port, "port", 4000, "Server port to listen on")
	flag.StringVar(&cfg.env, "env", "development", "Application environment (development|production")
	flag.Parse()

	fmt.Println("Running")

	http.HandleFunc("/status", func(w http.ResponseWriter, r *http.Request) {
		currentStatus := AppStatus{
			Status:      "Available",
			Environment: cfg.env,
			Version:     version,
		}

		js, err := json.MarshalIndent(currentStatus, "", "\t")
		if err != nil {
			log.Println(err)
		}

		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusOK)
		w.Write(js)
	})

	err := http.ListenAndServe(fmt.Sprintf(":%d", cfg.port), nil)
	if err != nil {
		log.Println(err)
	}
}

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


ไปที่เว็บเบราว์เซอร์ แสดงข้อมูลในรูปแบบ JSON


HttpRouter

HttpRouter เป็นเราเตอร์คำขอ HTTP ประสิทธิภาพสูงน้ำหนักเบา (เรียกอีกอย่างว่ามัลติเพล็กเซอร์หรือเรียกสั้นๆ ว่า mux) สำหรับ Go ติดตั้งโดยใช้คำสั่ง

go get -u github.com/julienschmidt/httprouter


สร้างไฟล์ routes.go ในโฟลเดอร์ api แล้วเขียนโค้ดดังนี้

package main

import (
	"net/http"

	"github.com/julienschmidt/httprouter"
)


func (app *application) routes() *httprouter.Router {
	router := httprouter.New()

	router.HandlerFunc(http.MethodGet, "/status", app.statusHandler)
	
	return router
}


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

package main

import (
	"flag"
	"fmt"
	"log"
	"net/http"
	"os"
	"time"
)

const version = "1.0.0"

type config struct {
	port int
	env  string
}

type AppStatus struct {
	Status      string `json:"status"`
	Environment string `json:"environment"`
	Version     string `json:"version"`
}

type application struct {
	config config
	logger *log.Logger
}

func main() {
	var cfg config

	flag.IntVar(&cfg.port, "port", 4000, "Server port to listen on")
	flag.StringVar(&cfg.env, "env", "development", "Application environment (development|production")
	flag.Parse()

	logger := log.New(os.Stdout, "", log.Ldate|log.Ltime)

	app := &application{
		config: cfg,
		logger: logger,
	}

	srv := &http.Server{
		Addr:         fmt.Sprintf(":%d", cfg.port),
		Handler:      app.routes(),
		IdleTimeout:  time.Minute,
		ReadTimeout:  10 * time.Second,
		WriteTimeout: 30 * time.Second,
	}

	logger.Println("Starting server on port", cfg.port)

	err := srv.ListenAndServe()
	if err != nil {
		log.Println(err)
	}
}



สร้างไฟล์ statusHandler.go ในโฟลเดอร์ api แล้วเขียนโค้ดดังนี้

package main

import (
	"encoding/json"
	"net/http"
)

func (app *application) statusHandler(w http.ResponseWriter, r *http.Request) {
	currentStatus := AppStatus{
		Status:      "Available",
		Environment: app.config.env,
		Version:     version,
	}

	js, err := json.MarshalIndent(currentStatus, "", "\t")
	if err != nil {
		app.logger.Println(err)
	}

	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)
	w.Write(js)
}


ทดสอบการทำงานด้วยคำสั่ง

go run ./cmd/api/ .

(go run ./cmd/api/ . เป็นคำสั่งที่ให้ทำงานทุกไฟล์ของ VSCode บน Windows สังเกต จะมีเว้นวรรคและ . อยู่หลังสุด ส่วน VSCode บน Mac นั้นจะใช้คำสั่ง go run ./cmd/api/*.go )


Firefox Browser


เว็บเบราว์เซอร์ที่ใช้ทดสอบเลือกเป็น Firefox Browser แล้วติดตั้ง Extension ชื่อ SP REST JSON เพิ่มเข้าไป

โดยปรกติการเปิดไฟล์ json บน browser จะเจอข้อมูล json ตามภาพด้านล่าง


ซึ่งถ้ามันมีข้อมูลมากๆ ที่ซับซ้อนมากยิ่งขึ้น จะทำให้อ่านยากมากและถ้าเราต้องเช็คความถูกต้องของโครงสร้าง json ด้วย ดังนั้นเลยมีผุ้พัฒนา SP REST JSON ขึ้นมาเพื่อติดตั้งบน browser ต่าง ๆ เช่น Firefox โดยเมื่อเราลง SP REST JSON แล้ว เมื่อเปิดไฟล์ json เลือกโหมด JSON เพจก็จะ render หน้าออกมาได้สวยงามดังรูปด้านล่าง

ทำให้เราสามารดูข้อมูล json เช่นดูโครงสร้างข้อมูล json , ตรวจสอบความถูกต้องของข้อมูลที่เก็บใน json เหล่านี้ได้ง่ายขึ้น

และยังสามารถดูแบบปรกติด้วยการเลือกโหมด Raw Data (คือ ข้อมูลดิบ ข้อมูลทุกรูปแบบที่ยังไม่ได้ผ่านการประมวลผล)

credit : https://www.udemy.com/course/working-with-react-and-go-golang/

Leave a Reply

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