มาฝึกใช้ Gin กันเถอะ !!!
บทความนี้เกิดจากว่า project ในที่ทำงานตัวนึง ใช้ Go ในการเขียน แล้วดั๊น !!!! ต้องไป fix bug ใน project นี้ เอาล่ะสิ จาก Nodejs developer ต้องไปเป็น Go developer ชั่วคราวแล้วสิ ก็เลยไปลองศึกษาเจ้าตัวนี้ให้มากขึ้น
หลังจากรู้ตัวว่าต้องไปทำโปรเจคนี้ อันดับแรกเลยลองไปดู code ของโปรเจคนี้ แบบยังไม่รู้อะไรเกี่ยวกับ golang มาก่อน ด้วยความอัจฉริยะ(ที่มโนไปเอง) โหววว เราก็อ่าน code ออก เขียนได้เหมือนกันนะเนี่ย (แค่ if else อ่านะ) เลยสามารถ แก้บัคของโปรเจคนี้ได้
แต่พอไปลองศึกษาแบบลึกขึ้น ไปดูตัวอย่าง code ของ โปรเจคอื่นๆ ที่ใช้ golang ก็พบว่า!!! ไอ้ตัวโปรเจคที่ทำมันไม่ได้ใช้ framework อะไรเลยนี่หว่า T__T code ก็เลยค่อนข้างเละ และ maintain ยากพอสมควร แถมพี่คนเก่าที่ขึ้นโปรเจคก็ออกไปแล้วอีก เราเลยไปลองศึกษาเพิ่มเติมว่า มีตัวช่วยอะไรบ้างน้าาา จนไปเจอกับ GIN web framework (https://github.com/gin-gonic/gin) ที่จะเป็นตัวช่วยให้ชีวิตสบายมากขึ้นนั่นเองงงงง
หลังจากเกริ่นมา 1 หน้ากระดาษ มาเข้าเรื่องกันเถอะ!!!
Gin คืออะไร
ผู้พัฒนาเขาบอกมาว่า
“Gin is a web framework written in Go (Golang). It features a martini-like API with performance that is up to 40 times faster thanks to HTTP router. If you need performance and good productivity, you will love Gin.”
ถ้าแปลเป็นไทย แบบภาษาบ้านๆก็คือ Gin เป็น web framework ที่เขียนด้วยภาษา Go มี features เหมือน martini API แต่มีประสิทธิภาพมากกว่า มีความเร็วมากกว่า httprouter ถึง 40 เท่า ถ้าเราต้องการ performance และ productivity ที่ดี คุณจะหลงรักคุณ Ginn นั่นเอง (มาทั้ง Gin และ Martini อ่านบทความจบแล้วอย่าลืมไปนั่งดื่มกันนะคะ 5555555)
มาดูข้อดีและข้อเสียของ Gin กันเถอะ
ข้อดี
- มีความมินิมอล ชิคๆ คูลๆ(ตามเทรนสุดๆ): ตัว Gin เนี่ย นักพัฒนาจะต้องการให้เจ้าตัวนี้ มินิมอลที่สุด จะมีแต่ features หรือ libralies สำคัญๆ เท่านั้น เหมาะสำหรับ service เล็กๆ ที่ไม่ซับซ้อน ทำให้ service ที่เราใช้ตัว Gin เนี่ยจะค่อนข้างรวดเร็ว
- debug ง่ายมาก: เนื่องจาก Gin มีวิธีการรวบรวม error ที่เกิดขึ้นระหว่าง process ยิง http request และส่งไปให้ middleware มา handle ต่อได้เลย
- มีการแบ่งกลุ่ม API ให้ง่ายต่อการใช้งาน: ตัว Gin เนี่ยจะมีการจัดกลุ่ม api ได้ว่า api ตัวไหน มีการ authorization บ้าง หรือ api ไหนที่จะให้ใช้ middleware ที่สร้างขึ้นมาได้บ้าง เราสามารถจัดกลุ่มได้อย่างไม่จำกัด
ข้อเสีย
- ไม่เหมาะกับโปรเจคระดับEnterprises: ถ้าโปรเจคที่คุณทำอยุ่เป็น monolith ที่มีความซับซ้อนสูง และมี backend ที่ใหญ่มาก Gin อาจจะไม่เหมาะกับโปรเจคสักเท่าไหร่
- ข้อจำกัดของ Gin: ในข้อดีก็ต้องมีข้อเสียเช่นกัน เจ้าตัว Gin ที่มีความมินิมอลมากๆ ซึ่งก็อาจะทำให้บาง feature หรือฟังก์ชั่นต่างๆ ที่จำเป็นต่อระบบอาจจะไม่มี (แต่ยังไม่เห็นเคสที่เจอข้อจำกัดสักเท่าไหร่ ถ้าเจอตัวอย่างอาจจะมาเสริมให้นะคะ)
หลังจากเรารุ้จัก GIN กันไปแล้ว ที่นี้เรามาลองใช้งานกันค่ะ
Install
เริ่มจาก install Gin กันก่อนเลยค่ะ แต่เดี๋ยวก่อน ก่อนที่จะ install Gin เราต้อง make sure ก่อนว่าเรา install go และตั้งค่า go workspace เรียบร้อยแล้วก่อนนะคะ
1. install Gin เลยค่ะ (support go version 1.11 ขึ้นไปนะคะ)
$ go get -u github.com/gin-gonic/gin
2. หลังจากติดตั้งเสร็จเรียบร้อย ก็ import Gin ใส่ในโค้ดของเราได้เลยค่ะ
import "github.com/gin-gonic/gin"
3. มาลองทดสอบกันค่ะว่า work ไหม โดยเราจะสร้างไฟล์เพื่อทดสอบ สมมติสร้างไฟล์ main.go ตาม code ด้านล่าง
โดย code นี้จะเป็นการเรียก /path ที่เป็น method GET ถ้าหากว่า เรา install GIN สำหรับ จะ response ออกมาเป็น {“message”:”pong”}
ทีนี้เรามาลองรันคำสั่ง
go run main.go
และเปิดเว็บ http://localhost:8080/ping
ถ้าผลลัพธ์ออกมาแบบนี้ แสดงว่าเราสามารถใช้งานได้แล้วค่ะ ไป step ต่อไป ซึ่งตัวอย่างนี้จะเป็นการสร้าง API แบบง่ายๆ ( CRUD ) มาดูกันเลยยย
ตัวอย่างการสร้าง API
เราสามารถสร้าง api route ที่มี method GET, POST, PUT, PATCH, DELETE และ OPTIONS ได้ ตามที่เราต้องการใช้ ในตัวอย่างนี้ สมมติว่าเราต้องการสร้าง service ที่ สามารถสร้าง user ขึ้นมา method หลักๆ ก็จะมี GET, POST, PUT และ DELETE ตามด้านล่าง
หลังจากสร้าง route เสร็จเรียบร้อย อาจจะมีสงสัยว่า เอ๊ะ แล้ว function การทำงานของแต่ method จะไปใส่ที่ไหนต่อล่ะ แล้ว ตัว body ที่ยิง request จะนำไปใช้อย่างไรต่อมาเราจะมาอธิบายเพิ่มเติมถึงตัว handler และ parameter ที่สำคัญต่างๆ ของ Gin
Handler
Handler คืออะไร??? Handler เป็นตัวที่มาจัดการ operation ต่างๆ ของแต่ละ method ข้างต้น ปกติทั่วไปจะใช้ *gin.Context
เป็น Context ในการรับส่งค่าต่างๆ จาก HTTP request หรือค่าที่ response กลับ (อารมณ์คล้ายๆ context ใน koa ถ้าใครเคยใช้ตัวนี้มาก่อนน่าจะคุ้นเคย)
นอกจากนี้ Gin ยังมี function จำเป็นต่างๆ เช่น
- c.Query: เป็นการดึงข้อมูลจาก parameter ของ request (คล้ายกับ context.params ใน koa)
- c.PostForm: จะเป็นการดึงข้อมูลจาก Multipart หรือ Urlencoded Form (คล้ายกับ context.request.body ใน koa)
- c.ShouldBindJSON: คือการ bind request body ให้เป็นในรูปแบบ JSON กับ struct
- c.Json: เป็นการคืนค่า response กลับไปให้ request
วิธีการใช้งานจะเป็นตามตัวอย่างด้านล่าง
จบไปแล้วค่ะกับตัวอย่างการสร้าง CRUD ของ user อย่างง่ายๆ ซึ่ง function ของ Gin ยังมีอีกเยอะมากเลยค่ะที่รองรับหลากหลายรูปแบบของข้อมูล และไม่ได้กล่าวถึงสามารถดูเพิ่มได้ได้ที่ https://godoc.org/github.com/gin-gonic/gin#Context เลยค่ะ
ต่อมาจะพูดถึงข้อดีที่กล่าวไปข้างต้นคือ “มีการแบ่งกลุ่ม API ให้ง่ายต่อการใช้งาน” นั่นก็คือ Group ของ api นั่นเอง
Routes grouping
routes grouping เป็นการจัดกลุ่ม routes ของ request ซึ่งตัวอย่างจะเป็นการแยก request ด้วย version ของ API และฟังก์ชั่นการทำงานของมัน
จาก code ตัวอย่างข้างบนจะเห็นว่า จะแยก request ออกมาเป็น version1 และเป็น request ที่เกี่ยวข้องกับ user ทั้งหมด ซึ่งการแยกแบบนี้จะทำให้ code เราเป็นระบบระเบียบมากขึ้น ง่ายต่อการนำไปใช้ต่อ และยังสามารถสร้าง middleware มาครอบเฉพาะกลุ่มได้
Middleware
Middle ware คืออะไร?? มันคือ function ตรงกลางที่เราสร้างขึ้นมาเพื่อมาช่วยจัดการ request และ response ก่อนหรือหลังใช้งาน api มีรูปแบบการใช้งานตามด้านล่าง
สมมติว่าเราสร้าง middleware มาสองตัวคือ exampleMiddleware และ adminMiddleware หากยิงไปที่ request /api/v1/users
ก่อนจะเริ่มทำงานในส่วน api จะผ่าน middleware ที่ชื่อว่า exampleMiddleware แต่หาก ยิงไปที่ request /api/v1/admin
จะผ่าน middleware ที่ชื่อว่า adminMiddleware ซึ่งเราสามารถสร้าง middleware แบบไหนมาได้เรื่อยๆ เลยค่ะ
สรุป
จบไปแล้วกับบทความแรกของการใช้ Gin !!! จากการทดลองใช้งาน Gin web framework ไประดับหนึ่ง ก็พบว่าใช้งานค่อนข้างง่าย (แต่เทียบกับ node แล้วก็ยังยากกว่าอยู่ดีค่ะ 55555) แต่ยังไม่ได้ทดสอบเรื่อง performance กับ productivity เทียบกับ framework ตัวอื่นๆ ที่เขาเคลมว่าดีมากเลยค่ะ ซึ่งตอนนี้เราก็ยังศึกษาและลองเล่นเรื่อยๆ มีอะไรให้เล่นอีกเยอะมากเลยค่ะ ทั้งการ Test, logging file, validation บลาๆๆ คาดว่าบทความหน้าจะมาอธิบายและสอนการใช้งานเรื่องพวกนี้เพิ่มเติม แล้วพบกันใหม่บทความหน้านะคะ :)))