Models ภาษา Go
Model (โมเดล) คือออบเจกต์ที่ทำหน้าเป็นตัวแทนของข้อมูล ไม่ว่าข้อมูลจะถูกจัดเก็บในรูปแบบใดในระบบฐานข้อมูลหรือในไฟล์ เมื่อข้อมูลนั้นถูกโหลดเข้ามาในแอพพลิเคชัน เราจะเปลี่ยนมันให้อยู่ในรูปของออบเจกต์ และเราเรียกบทบาทของออบเจกต์นี้ว่า “Model” ยกตัวอย่างเช่นออบเจกต์ Customer, Employee, Product เป็นต้น
และ ไม่ว่าข้อมูลนั้น ๆ จะถูกจัดเก็บในรูปแบบใดก็ตาม ในฐานข้อมูล แบบเป็น Object Class หรือที่นิยมเรียกกันว่า VO ( Value Object ) หรือเก็บเป็นไฟล์ข้อมูลเลย เมื่อข้อมูลถูกโหลดเข้ามาจากที่ต่าง ๆ และเข้ามายังส่วนของโมเดล ตัวโมเดลจะทำการจัดการตระเตรียม ข้อมูลให้เป็นรูปแบบที่เหมาะสม
ข้อกำหนดเบื้องต้น
ข้อกำหนดสำหรับบทความนี้คือ คุณต้องติดตั้ง 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/