หัด Golang part 2
เขียน RESTful API ด้วย encoding/json package
อ่านเนื้อหาก่อนหน้า ที่นี่
เพื่อนๆมือใหม่อาจยังไม่รู้จัก RESTful API ว่ามันคืออะไร การให้บริการ resources เป็นอย่างไร และจะสามารถเข้าถึงผ่าน HTTP ได้อย่างไร เชิญอ่านก่อน
พอเข้าใจและมีความรู้ใน RESTful API จึงถึงเวลาของ Golang
จับ Request แล้วส่ง Response กลับไปด้วย net/http
จากโค้ดมาดูทีละส่วน
import "net/http"
บอกว่าขอ net/http package มาจัดการเรื่อง HTTP รายละเอียด
func home(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "<h1>Home</h1>")}
home function นี้รับพารามิเตอร์ 2 ตัว ได้แก่ ResponseWriter และ *Request ซึ่งจะถูก inject จาก HandleFunc function อีกทีหนึ่ง หน้าที่ของมันคือสร้างหน้า Home แล้วส่งไปหา client ที่เรียก
func handleRequests() { http.HandleFunc("/", home) http.ListenAndServe(":8080", nil)}
handleRequests function ทำหน้าที่จับ request url ที่ร้องขอจาก client หัวใจคือฟังก์ชันชื่อ HandleFunc ซึ่งมีหน้าตาดังนี้
func HandleFunc(pattern string, handler func(ResponseWriter, *Request))
ทั้งนี้ handleRequests ยังเรียก ListenAndServe function เพื่อเริ่ม server ที่ port หมายเลข 8080
รันอีกครั้ง
และเรียกไป
http://localhost:8080/
ก็จะได้ผล
หากต้องการหยุด server ก็พิมพ์
ctrl + c
หน้าแรกของเราสร้างกันง่ายมาก แต่มันยังไม่ใช่ RESTFul API แบบที่ให้ผลลัพธ์เป็น JSON อย่างนั้นเรามาสร้าง GET resource ตัวแรกกันเถอะ
struct
จำได้ไหมภาษา C เวลาจะประกาศโครงสร้าง เราจะต้องใช้ struct
เอาเป็นหนังสือสักเล่มหนึ่ง น่าจะประกอบด้วยอะไรบ้าง อื่ม…
- ISBN
- name
- author name
- year
- total page
ประมาณนี้ ก็สามารถสร้าง struct ได้หน้าตาแบบนี้
type book struct { Isbn string Name string AuthorName string Year string TotalPage int}
เราจะสร้าง function ที่รับผิดชอบเรื่องนี้ชื่อ getAllBooks
func getAllBooks(w http.ResponseWriter, r *http.Request)
และสร้าง URI path ให้ในฟังก์ชัน handleRequests
http.HandleFunc("/books", getAllBooks)
เนื่องจากว่า GET /books ของเราให้ผลเป็นหนังสือหลายเล่มได้ ฉะนั้นเราจัดการด้วย Array ไปเลย
allBooks := []book{ }
เมื่อ allBooks คือชื่อตัวแปรแบบกำหนดไทป์เป็น []book จึงได้ว่าภายในจะต้องประกอบด้วย book หลายๆเล่ม (เอาสัก 2 เล่ม)
ตัวอย่าง book หนึ่งเล่มหน้าตาจะเป็นแบบนี้
book { Isbn: "978-616-08-2539-4", Name: "พัฒนาเว็บแอปพลิเคชั่นด้วย JavaScript", AuthorName: "จตุรพัชร์ พัฒนทรงศิวิไล", Year: "2529", TotalPage: 460,},
สุดท้ายเราจะต้องแปลง struct ให้กลายเป็น JSON ผ่านฟังก์ชัน NewEncoder
json.NewEncoder(w).Encode(allBooks)
และการจะใช้มันได้ต้องใช้ package ชื่อ “encoding/json” รายละเอียด
ใน Golang เมื่อมีการประกาศใช้ package มากๆก็สามารถประกาศรวมกันได้
import ( "fmt" "net/http" "encoding/json")
โค้ดทั้งหมด
rerun server ใหม่ แล้วมาดูผลลัพธ์
จาก resource ที่เห็น สิ่งหนึ่งที่ผมไม่ชอบคืออักษรตัวพิมพ์ใหญ่ขึ้นต้น (Isbn, Name, AuthorName, Year, TotalPage) ที่ต้องเป็นพิมพ์ใหญ่ก็เพราะใน Golang การเขียนพิมพ์ใหญ่จะให้ modifier เป็น public ตรงกันข้ามกับพิมพ์เล็กจะให้ผลเป็น private และถ้าเป็น private ก็จะออก JSON ไม่ได้ (ก็ผมอยากได้พิมพ์เล็กอะ)
สมมติให้ TotalPage ใน struct เขียนเป็น totalPage ผลลัพธ์จะเป็นแบบนี้
แก้ไขอย่างไร?
ทางออกคือเขียนเพิ่ม บอกมันไปว่าต้องการประดิษฐ์ชื่อคีย์เอง (จะเอาพิมพ์เล็กๆ) ตัวอย่าง
`json:"isbn"`
*หมายเหตุ ระหว่างเครื่องหมาย ` และ ` นี่ต้องเขียนโค้ดให้ติดกันนะ ห้ามเว้นว่าง จึงได้ว่า
type book struct { Isbn string `json:"isbn"` Name string `json:"name"` AuthorName string `json:"authorName"` Year string `json:"year"` TotalPage int `json:"totalPage"`}
rerun server ใหม่ แล้วมาดูผลลัพธ์
RESTful API ที่เรารู้จักมาจะประกอบไปด้วย verb 4 อย่าง ได้แก่ GET, POST, PUT and DELETE รวมแล้วเรียกว่า CRUD ดังนั้นโอกาสถัดไปเราจะมาทำให้ครบ โดยเพิ่มเติมคือเชื่อมต่อกับฐานข้อมูลด้วย
part นี้ลาแล้วสวัสดีครับ