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,寫的很詳細了。

20191117-1-go mod文件.png

這就是我的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、點擊執行該程序

20191117-2-運行helloworld.gif

從控制臺程序可以看出服務已經啟動,并且開始監聽8080端口

3、訪問接口

接下來我們在瀏覽器輸入localhost:8080/ping即可看到程序返回的結果

20191117-3-運行helloworld.gif

一個極簡的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模板文件目錄結構如下

20191117-4-目錄結構.gif

代碼部分

router.LoadHTMLGlob用于指明HTML模板文件的路徑

router.GET同上,定義訪問路由和返回結果,不同于第一個Demo的是,這里有賦值填充的過程,比如

c.HTML(http.StatusOK, "posts/index.tmpl", gin.H{
            "title": "Posts",
        })

將index.tmpl中定義的.title替換為"Posts"

執行結果如下

20191117-5-模板運行.gif

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()方法。

啟動程序后,我們看下訪問結果有什么不同

20191117-6-purejso.gif

可以看出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的源碼。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 轉發自:http://shanshanpt.github.io/2016/05/03/go-gin.html gi...
    dncmn閱讀 6,071評論 0 1
  • 所謂框架 框架一直是敏捷開發中的利器,能讓開發者很快的上手并做出應用,甚至有的時候,脫離了框架,一些開發者都不會寫...
    人世間閱讀 216,332評論 11 242
  • Go語言web框架學習—Gin 開發環境:操作系統:ubuntu1804 x64Golang 版本:go1.12....
    蔻蔻噠閱讀 1,677評論 0 1
  • 給大家講講我小時候生活過的地方,人都有長大的一天,正如那首歌中所唱,我不想不想長大,可是沒辦法,一個人總要面對長大...
    穆清遠閱讀 405評論 0 1
  • 這兩天我好郁悶。感覺。寶寶的爸爸,越看越不順眼。什么事情,都讓我看得很不順心。每次讓她抱著寶寶,干一下活,他都會抱...
    小佳丶_ebcd閱讀 234評論 0 0