這是我第一次利用極度不熟的 GO 語法搭建網站後台,依照直覺當然是先找一個最多人用的後台框架來實驗。
網路上對於 GO 來說很多人都會推薦 GIN 來當做後台框架的首選,因此我就找了 GIN 框架來實作一下。
安裝 Gin 套件
實作前還是要先記錄一下 Gin 的安裝
下載 Gin 套件
$ go get -u github.com/gin-gonic/gin
需符合 go 最小版本 v1.11
測試 Gin 套件
package main
import "github.com/gin-gonic/gin"
func main() {
r := gin.Default()
r.GET("/ping", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "pong",
})
})
r.Run() // listen and serve on 0.0.0.0:8080 (for windows "localhost:8080")
}
執行 gin 服務
go run example.go
開瀏覽器測試
localhost:8080/ping
教學範例
Building Go Web Applications and Microservices Using Gin
實作
依照上面那個連結來實作一個簡單的 GIN 框架,包含幾個頁面與 Endpoint,最後的成果放在這裡。
我沒有實作最後面的 利用 Semaphore 整合 Github 來做 CI/CD 的部份,因為我覺得實際上在公司內的專案大部份的程式大概不會放在 Github 上,而且以公司內的專案來說,可能會架設自用的 Jenkins 或甚至利用公司內部的 Gitlab 來跑 Runner 以實行 CI / CD,因此我就先跳過 Semaphore 的部份。
因此我這次實作的內容包括:
- 安裝 GOLANG / Gin
- 設定好 Visual Code 的 Go 環境
- 創建最簡單且可以接受 Request 的 Gin 框架
- 加上 templates 資料夾,並在 templates 資料夾中開始加入許多組合頁面
- 讓 Gin 可以讀取 templates 資料夾中的頁面
- 讓 Gin 可以依照不同 Request 指定到不同的 Endpoint ,且呈現相對應的網頁頁面
- 創建虛擬網頁資料,原本應該是要從資料庫讀取,這裡為了方便起見會先用 struct 寫死在一個程式檔案中
- Gin 網頁資料可以動態的讀取上述的資料集並呈現在網頁中
- 根據 Request 的標頭來判斷需回應的型式,包括最簡單的網頁,Json 以及 XML
- 撰寫測試程式,且可以一次執行所有的測試程式
詭異的表情=.=
- 一開始在考慮到底是在 Windows 安裝還是在 Ubuntu 系統中安裝,我一開始是覺得在 Ubuntu 安裝要裝什麼都自己來應該是 OK,但是後來遇到一個狀況是我要安裝 Gin 套件時,我的 GOLANG 版本過舊,必須從 10 升到 11 ,光這個部份,我花了很多時間去找方法解安裝 v10 ,重新安裝 v11 ,再設定 GoLANG 的 PATH,因為 v10 和 v11 有一些 path 預設不一樣,最後才安裝 Gin 套件。現在想想如果是在 Windows 架構下,因為是使用 Chocolatey 來幫忙安裝 GOLANG,所以就算要重新安裝或更新新版,這些環境變數應該不用自己設定,可能會方便許多。
- Visual Code 的 Go 套件 就是微軟出品的那個 真的很方便,幾乎裝完了這個套件後,其他不足的套件它會自動提示你,所以就照著它說的繼續裝完就好了,不用擔心自己什麼沒裝,真的很可以。
- GOLANG 有內建單元測試套件,可以非常快速的針對所寫的程式做測試,這就是為什麼這個教學裡有那麼多 xxx_test.go 的檔案,我之後會針對這個部份再多做幾個小練習。
- 就這個練習來看,我覺得利用 GOLANG 搭配 Gin 架設一個後端平台真的是蠻快速的,幾乎在架設網站一開始會遇到的問題他都有快速的解決方法,例如簡潔的製作多個入口,跟網頁搭配呈現方式,甚至快速符合不同需求吐回資料等等。
- 目前對我來說最大的問題反而是 GO 語言的掌握度不足,雖然我很高興我又從半直譯式語言 (Python) 跳回到編譯式語言,但是 GO 的習慣又不符合 OOP 的架構,更不用說又把我極度討厭的 C 程式裡的指標給搬出來了,雖然說 GO 這邊對於指標的使用是大大的減化了,但是看起來練習的路還有一段要走。
GOLANG 新手就是會碰到的腦殘問題
struct 問題
type article struct { ID int json:"id" Title string json:"title" Content string json:"content" }
在 models.article.go 那個部份的程式有出現上面這個struct,我一直編譯不過,然後才知道它打錯了,正確的應該是
# 正確寫法 type article struct { ID int `json:"id"` Title string `json:"title"` Content string `json:"content"` }
有發現不一樣的地方了嗎? 正確的會在每一行的最後面的前後加上那個小點點,上網查了才知道原來這是 GOLANG 的語法之一,而且那個鍵是利用鍵盤上的 1 的左邊那個按鍵,有很多人會把它按成是 Enter 左邊那個按鍵。基本上在 struct 裡有一個語法叫做 TAG 的語法,就是放在 struct 最後面的 ‵json:"id"‵ 這一串,需要用1左邊那個按鍵去把它給括起來。裡面是一個 key-value 的組合,前面的 key 是一個已經定義好的部份,by golang ,例如 json 就是它已經定義好的,它的作用是直接可以幫你把這個欄位當碰到特殊的狀況,例如 json 格式時,直接轉換成你 tag 裡所定義好的 value。
大括號問題
func initializeRoutes() { router.GET("/", showIndexPage) }
我一開始會把第一行的括號往下放,例如
func initializeRoutes() { router.GET("/", showIndexPage) }
在很多其他的程式語言,例如 Java ,這樣的寫法沒什麼特別的,但是偏偏在 GOLANG 裡,這樣是編譯不過的,原因是因為,GO 編譯器其實會主動在特定的字元後面做分段,也就是加上 ; ,因此如果是我自己寫法的話,就會變成
func initializeRoutes(); { router.GET("/", showIndexPage) }
很明顯的這會有問題對吧,所以在 GOLANG 裡,func 後面的大括號請不要主動移到下一行,謝謝。