Models ภาษา Go


Model (โมเดล) คือออบเจกต์ที่ทำหน้าเป็นตัวแทนของข้อมูล ไม่ว่าข้อมูลจะถูกจัดเก็บในรูปแบบใดในระบบฐานข้อมูลหรือในไฟล์ เมื่อข้อมูลนั้นถูกโหลดเข้ามาในแอพพลิเคชัน เราจะเปลี่ยนมันให้อยู่ในรูปของออบเจกต์ และเราเรียกบทบาทของออบเจกต์นี้ว่า “Model” ยกตัวอย่างเช่นออบเจกต์ Customer, Employee, Product เป็นต้น

และ ไม่ว่าข้อมูลนั้น ๆ จะถูกจัดเก็บในรูปแบบใดก็ตาม ในฐานข้อมูล แบบเป็น Object Class หรือที่นิยมเรียกกันว่า VO ( Value Object ) หรือเก็บเป็นไฟล์ข้อมูลเลย เมื่อข้อมูลถูกโหลดเข้ามาจากที่ต่าง ๆ และเข้ามายังส่วนของโมเดล ตัวโมเดลจะทำการจัดการตระเตรียม ข้อมูลให้เป็นรูปแบบที่เหมาะสม

Models ภาษา Go


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


ข้อกำหนดสำหรับบทความนี้คือ คุณต้องติดตั้ง Go และ ปฏิบัติตามบทความ Router และ Handlers มาก่อน


New Package


เรากำลังให้บริการ movies ดังนั้นเรามาสร้างประเภทเพื่อเก็บ movies กัน แล้วเราก็สามารถสร้างเส้นทางเดียวในการรับ movies เรื่องหนึ่งอย่าง Jason และอีกเส้นทางหนึ่งในการรับ collection ของ movies

สร้างโฟลเดอร์ ชื่อ models ภายในโฟลเดอร์ backend-app และ จะกลายเป็น Models ฐานข้อมูลในที่สุด


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


Struct

Struct คือ ชนิดของข้อมูล หรือโครงสร้างของข้อมูล ที่เราสามารถกำหนดเองได้ โดยภายใน Struct เราจะมี Field ของข้อมูลต่างๆ เก็บไว้ โดย keyword คำว่า “type” บอกถึงว่า เรากำลังจะประกาศ ชนิดข้อมูลใหม่ ตามด้วยชื่อของ โครงสร้างข้อมูล “ Movie” , “ Genre” และ “MovieGenre” คำว่า “struct” บอกถึงว่า เราได้กำหนด type ขึ้นมาเป็น โครงสร้างข้อมูล (struct type) โดยภายใน Struct เราจะมี list ของ field ข้อมูล พร้อมด้วยการประกาศ data type ของแต่ละ field


โดยเราจะสร้าง struct  3 ประเภท สำหรับเก็บข้อมูล movies

package models

import "time"

type Movie struct {
	ID          int          `json:"id"`
	Title       string       `json:"title"`
	Description string       `json:"description"`
	Year        int          `json:"year"`
	ReleaseDate time.Time    `json:"release_date"`
	Runtime     int          `json:"runtime"`
	Rating      int          `json:"rating"`
	MPAARating  string       `json:"mpaa_rating"`
	CreatedAt   time.Time    `json:"created_at"`
	UpdatedAt   time.Time    `json:"updatedAt"`
	MovieGenre  []MovieGenre `json:"-"`
}

type Genre struct {
	ID        int       `json:"id"`
	GenreName string    `json:"genre_name"`
	CreatedAt time.Time `json:"created_at"`
	UpdatedAt time.Time `json:"updatedAt"`
}

type MovieGenre struct {
	ID        int       `json:"id"`
	MovieID   int       `json:"movie_id"`
	GenreID   int       `json:"genre_id"`
	Genre     Genre     `json:"genre"`
	CreatedAt time.Time `json:"created_at"`
	UpdatedAt time.Time `json:"updatedAt"`
}


Simple API Route


สร้างไฟล์ใหม่ในโฟลเดอร์ api ชื่อ movie-handlers.go โดยเราจะใส่ตัวจัดการ movies ทั้งหมด ไว้ที่นี่

package main

import (
	"backend/models"
	"errors"
	"net/http"
	"strconv"
	"time"

	"github.com/julienschmidt/httprouter"
)

func (app *application) getOneMovie(w http.ResponseWriter, r *http.Request) {
	params := httprouter.ParamsFromContext(r.Context())

	id, err := strconv.Atoi(params.ByName("id"))
	if err != nil {
		app.logger.Print(errors.New("invalid id parameter"))
	}

	app.logger.Println("id is", id)

	movie := models.Movie {
		ID: id,
		Title: "Some movie",
		Description: "Some description",
		Year: 2021,
		ReleaseDate: time.Date(2021, 01, 01, 01, 0, 0, 0, time.Local),
		Runtime: 100,
		Rating: 5,
		MPAARating: "PG-13",
		CreatedAt: time.Now(),
		UpdatedAt: time.Now(),
	}

	err = app.writeJSON(w, http.StatusOK, movie, "movie")
}

func (app *application) getAllMovies(w http.ResponseWriter, r *http.Request) {
	
}


ที่ไฟล์ routes.go เขียนโค้ดเพิ่มดังนี้ และตอนนี้เรามีเส้นทางใหม่สองเส้นทาง

	router.HandlerFunc(http.MethodGet, "/v1/movie/:id", app.getOneMovie)
	router.HandlerFunc(http.MethodGet, "/v1/movies", app.getAllMovies)


สร้างไฟล์ใหม่ในโฟลเดอร์ api ชื่อ utilties.go สิ่งที่ต้องการทำที่นี่คือการเขียนฟังก์ชันง่าย ๆ ที่จะเขียน Json ไปยังเบราว์เซอร์

package main

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

func (app *application) writeJSON(w http.ResponseWriter, status int, data interface{}, wrap string) error {
	wrapper := make(map[string]interface{})

	wrapper[wrap] = data

	js, err := json.Marshal(wrapper)
	if err != nil {
		return err
	}

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

	return nil
}

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

go run ./cmd/api/ .


ไปที่เว็บเบราว์เซอร์ป้อน url เป็น http://localhost:4000/v1/movie/10

จะเห็นว่าการแสดงเนื้อหาที่สมบูรณ์ และสังเกตว่าที่เราใช้เป็น movie มันจะถูกห่อด้วยกุญแจ


ถ้าดูที่โหมด Raw Data จะเป็นข้อมูลดิบที่มาเป็นบรรทัดเดียว


แต่ถ้าเลือกใช้ Pretty Print จะเปลี่ยนการแสดงจึงดูดีขึ้นนิดหน่อย

Prettyprint (หรือภาพพิมพ์สวย) คือการประยุกต์ใช้รูปแบบการจัดรูปแบบโวหารต่างๆกับข้อความซอร์สโค้ดมาร์กอัปและเนื้อหาประเภทอื่นที่คล้ายคลึงกัน รูปแบบการจัดรูปแบบเหล่านี้มักประกอบด้วยการเปลี่ยนแปลงในการวางตำแหน่งระยะห่างสีความคมชัดขนาดและการปรับเปลี่ยนที่คล้ายกันซึ่งมีจุดมุ่งหมายเพื่อให้ผู้คนดูอ่านและเข้าใจเนื้อหาได้ง่ายขึ้น


และนี่คือวิธีหนึ่งในการรับข้อมูลที่ส่งไปยังผู้ใช้ปลายทางของเรา แล้ว ทดสอบเปลี่ยน id จาก 10 เป็น 20 ควรจะได้การแสดงเนื้อหาที่เหมือนกัน


Improved error handling


ภาษา Go นั้นในแต่ละ method จะทำการ return ค่า Error กลับมาเสมอ เพื่อบอกสถานะของการทำงานว่าเป็นอย่างไร ถ้า Error เป็น nil แสดงว่ามีสถานะเป็นปกติ แต่ถ้าไม่ nil หมายถึงเกิดเหตุการณ์ที่ไม่ปกติขึ้นมาแล้ว ดังนั้น developer สามารถจัดการกับ Error ได้ง่ายมาก ๆ

ไปที่เว็บเบราว์เซอร์ของเราแล้วเปลี่ยนจาก 20 เป็น alpha และคุณเห็นว่ามันยังคงโยน JSON กลับด้วยแนวคิดที่เป็น 0 ซึ่งไม่มีประโยชน์เลยเพราะเมื่อ เรากำลังสืบค้นฐานข้อมูลอยู่ จะไม่มีข้อมูลนี้อยู่ที่นั่น เนื่องจากเราไม่ได้ค้นหาสิ่งต่าง ๆ ในฐานข้อมูล มิฉะนั้นเราจะไม่ใช่ค่าตัวเลขและตัวอักษร เรากำลังค้นหาด้วยจำนวนเต็มเท่านั้น

ดังนั้นเราจึงต้องแก้ไขและนั่นก็ทำได้ง่ายมาก ดังนั้นฉันจะกลับไปที่ไฟล์ utilties.go และ เพิ่มโค้ด

package main

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

func (app *application) writeJSON(w http.ResponseWriter, status int, data interface{}, wrap string) error {
	wrapper := make(map[string]interface{})

	wrapper[wrap] = data

	js, err := json.Marshal(wrapper)
	if err != nil {
		return err
	}

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

	return nil
}

func (app *application) errorJSON(w http.ResponseWriter, err error) {
	type jsonError struct {
		Message string `json:"message"`
	}

	theError := jsonError{
		Message: err.Error(),
	}

	app.writeJSON(w, http.StatusBadRequest, theError, "error")
}


ที่ ไฟล์ movie-handlers.go เพิ่มโค้ด แล้วทดสอบการทำงาน

app.errorJSON(w, err)
return



กลับไปที่เว็บเบราว์เซอร์แล้วไปที่ http://localhost:4000/v1/movie/1 หน้าเพจควรให้ JSON ที่ถูกต้อง และเป็นเช่นนั้น


และเมื่อเปลี่ยนเป็นข้อความเป็น beta แทนที่ 1 ตอนนี้เราจะได้รับข้อความแสดงข้อผิดพลาด

เราอาจกลับไปเปลี่ยนตัวจัดการนั้นเพื่อให้เราระบุสถานะเฉพาะได้ แทนที่จะเป็นเพียงแค่คำขอที่ไม่ดี แต่นี่ก็เพียงพอแล้วสำหรับจุดประสงค์ของเราในตอนนี้


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 *