Go元件學習——Web框架Gin
以前學Java的時候,和Spring全家桶打好關係就行了,從Spring、Spring MVC到SpringBoot,一脈相承。
對於一個Web專案,使用Spring MVC,就可以基於MVC的思想開發專案了,不管是應對前後端分離還是不分離的場景,你都可以輕鬆駕馭。因為你只要知道,你用的是一個Web開發框架就行了。
相比於Spring在Java一家獨大的局面,Go生態中的Web框架還在百家爭鳴的階段。從今天開始學習一款基於Go語言開發的Web開發框架Gin。
簡介
Github:https://github.com/gin-gonic/gin
語言:Go語言
官網:https://gin-gonic.com/
環境搭建
Go版本:1.12.4
系統:macOS
依賴管理工具:go mod
IDE:Goland
因為我使用了go mod,所以引用gin的依賴算是很方便了。
如何建立一個go mod管理的新專案以及如何將老專案改造為go mod,可以參見這篇文章:https://juejin.im/post/5c8e503a6fb9a070d878184a,寫的很詳細了。
這就是我的go-demo:https://github.com/DMinerJackie/go-demo專案的所有第三方依賴了。
那麼如何新增gin的依賴呢?有以下三種方式
-
直接新建一個基於gin的example程式檔案,然後執行
go build xxx.go
go run xxx.go
命令,go mod就會自動幫你下載gin依賴並更新go.mod檔案。 -
同上,還是新建一個example程式檔案,然後在專案根目錄下執行
go mod tidy
命令,go mod會幫你安排上。這個命令可以幫助你移除不需要的依賴,並拉取引用你需要的依賴。 -
在go.mod檔案中手動新增依賴類似
github.com/gin-gonic/gin v1.4.0
這種。
幾乎不用什麼繁瑣的步驟,就完成了環境搭建。下面開始寫第一個基於Gin的demo
第一個Demo
1、新建檔案helloworld.go
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() // 監聽並在 0.0.0.0:8080 上啟動服務 }
2、點選執行該程式
從控制檯程式可以看出服務已經啟動,並且開始監聽8080埠
3、訪問介面
接下來我們在瀏覽器輸入localhost:8080/ping即可看到程式返回的結果
一個極簡的Web伺服器就這樣搭建完成並對外訪問了。
上面的程式碼中
通過 r:=gin.Default()
宣告一個gin的引擎,後續的操作都是基於這個引擎的。
通過 r.GET
申明一個可以訪問的路由,定義的HTTP請求方式為GET請求。同時定義了請求後對應的處理方式,即一個閉包函式宣告以JSON格式返回的鍵值對。
通過 r.Run()
監聽指定埠並啟動服務
其他Demo
1、渲染HTML
雖然現在很多都倡導並實行前後端分離了,即後端只提供HTTP介面,前端負責呼叫HTTP介面以及頁面渲染。
但還是有前後端揉在一起的使用場景,gin就提供了這種能力。
具體的做法是提供一個HTML模板,服務端將得到的資料填充到模板中實現頁面的渲染。
import ( "github.com/gin-gonic/gin" "net/http" ) func main() { router := gin.Default() router.LoadHTMLGlob("main/src/gin-example/examples/templates/**/*") router.GET("/posts/index", func(c *gin.Context) { c.HTML(http.StatusOK, "posts/index.tmpl", gin.H{ "title": "Posts", }) }) router.GET("/users/index", func(c *gin.Context) { c.HTML(http.StatusOK, "users/index.tmpl", gin.H{ "title": "Users", }) }) router.Run(":8080") }
index.tmpl
{{ define "posts/index.tmpl" }} <html><h1> {{ .title }} </h1> <p>Using posts/index.tmpl</p> </html> {{ end }}
user.tmpl
{{ define "users/index.tmpl" }} <html><h1> {{ .title }} </h1> <p>Using users/index.tmpl</p> </html> {{ end }}
對應的HTML模板檔案目錄結構如下
程式碼部分
router.LoadHTMLGlob
用於指明HTML模板檔案的路徑
router.GET
同上,定義訪問路由和返回結果,不同於第一個Demo的是,這裡有賦值填充的過程,比如
c.HTML(http.StatusOK, "posts/index.tmpl", gin.H{ "title": "Posts", })
將index.tmpl中定義的 .title
替換為"Posts"
執行結果如下
2、PureJSON
func main() { r := gin.Default() // 提供 unicode 實體 r.GET("/json", func(c *gin.Context) { c.JSON(200, gin.H{ "html": "<b>Hello, 世界!</b>", }) }) // 提供字面字元 r.GET("/purejson", func(c *gin.Context) { c.PureJSON(200, gin.H{ "html": "<b>Hello, 世界!</b>", }) }) // 監聽並在 0.0.0.0:8080 上啟動服務 r.Run(":8080") }
這裡兩個GET方法唯一不同的就是要渲染的內容一個使用JSON()方法一個使用PureJSON()方法。
啟動程式後,我們看下訪問結果有什麼不同
可以看出JSON()渲染的會有中文以及標籤轉為unicode編碼,但是使用PureJSON()渲染就是原樣輸出(我的瀏覽器裝了外掛,會自動解碼,所以不點選右邊的”RAW“兩個介面返回的結果是一樣的)。
這個問題,本週我們服務端在和客戶端對接的時候還遇到了,因為框架返回的JSON串就是經過編碼的,但是單獨請求放到瀏覽器是沒有問題的,客戶端收到的卻是經過編碼的,最後排查發現是瀏覽器外掛解碼了。
3、渲染多種資料交換格式的資料
gin支援渲染XML、JSON、YAML和ProtoBuf等多種資料格式
import ( "github.com/gin-gonic/gin" "github.com/gin-gonic/gin/testdata/protoexample" "net/http" ) func main() { r := gin.Default() // gin.H 是 map[string]interface{} 的一種快捷方式 r.GET("/someJSON", func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"message": "hey", "status": http.StatusOK}) }) r.GET("/moreJSON", func(c *gin.Context) { // 你也可以使用一個結構體 var msg struct { Name string `json:"user"` Message string Number int } msg.Name = "Lena" msg.Message = "hey" msg.Number = 123 // 注意 msg.Name 在 JSON 中變成了 "user" // 將輸出:{"user": "Lena", "Message": "hey", "Number": 123} c.JSON(http.StatusOK, msg) }) r.GET("/someXML", func(c *gin.Context) { c.XML(http.StatusOK, gin.H{"message": "hey", "status": http.StatusOK}) }) r.GET("/someYAML", func(c *gin.Context) { c.YAML(http.StatusOK, gin.H{"message": "hey", "status": http.StatusOK}) }) r.GET("/someProtoBuf", func(c *gin.Context) { reps := []int64{int64(1), int64(2)} label := "test" // protobuf 的具體定義寫在 testdata/protoexample 檔案中。 data := &protoexample.Test{ Label: &label, Reps: reps, } // 請注意,資料在響應中變為二進位制資料 // 將輸出被 protoexample.Test protobuf 序列化了的資料 c.ProtoBuf(http.StatusOK, data) }) // 監聽並在 0.0.0.0:8080 上啟動服務 r.Run(":8080") }
今天先到這,後面再看看gin的原始碼。
如果您覺得閱讀本文對您有幫助,請點一下“推薦”按鈕,您的“推薦”將是我最大的寫作動力!如果您想持續關注我的文章,請掃描二維碼,關注JackieZheng的微信公眾號,我會將我的文章推送給您,並和您一起分享我日常閱讀過的優質文章。