GO學(xué)習(xí)筆記(22) - 第三方框架-gin框架

目錄

  • 簡介
  • 生態(tài)框架
  • 安裝配置
  • 入門指南

簡介

其實對于golang而言,web框架的依賴要遠(yuǎn)比Python,Java之類的要小。自身的net/http足夠簡單,性能也非常不錯??蚣芨袷且恍┏S煤瘮?shù)或者工具的集合。借助框架開發(fā),不僅可以省去很多常用的封裝帶來的時間,也有助于團(tuán)隊的編碼風(fēng)格和形成規(guī)范。

Gin 是一個基于 Go 語言編寫的 Web 框架,比近似框架 martini 擁有更好的性能,借助高性能的 httprouter,速度提升了近 40 倍。詳細(xì)介紹

gin框架應(yīng)用

  • gorush:Go 編寫的通知推送服務(wù)器。
  • fnproject:容器原生,云 serverless 平臺。
  • photoprism:基于 Go 和 Google TensorFlow 實現(xiàn)的個人照片管理工具。
  • krakend:擁有中間件的超高性能 API 網(wǎng)關(guān)。
  • picfit:Go 編寫的圖像尺寸調(diào)整服務(wù)器。
  • gotify:基于 WebSocket 進(jìn)行實時消息收發(fā)的簡單服務(wù)器。
  • cds:企業(yè)級持續(xù)交付和 DevOps 自動化開源平臺。

安裝配置

  1. 添加環(huán)境變量
GO111MODULE  on
GOPROXY  https://goproxy.cn
GOROOT   是你安裝go的路徑
  1. 安裝
go get -u github.com/gin-gonic/gin
  1. 高性能日志庫zap安裝
go get -u go.uber.org/zap

基礎(chǔ)編程

  • 啟動默認(rèn)引擎(端口8080)
  • middleware應(yīng)用
  • context的使用
package main

import (
    "github.com/gin-gonic/gin"
    "go.uber.org/zap"
    "math/rand"
    "time"
)

const keyRequestId = "requestId"

func main() {
    //默認(rèn)服務(wù)端引擎
    //http://localhost:8080/ping
    //自動帶有日志模塊
    r := gin.Default()

    log,err := zap.NewProduction()
    if err != nil{
        panic(err)
    }

    //使用middleware,接入zap日志模塊
    r.Use(func(c *gin.Context) {
        //path,response code,log latency,
        start := time.Now()
        c.Next()

        log.Info("incoming request",
            zap.String("path",c.Request.URL.Path),
            zap.Int("status",c.Writer.Status()),
            zap.Duration("elapsed", time.Now().Sub(start)),

        )
    },
    //另外一個use
    //入口,增加requestId
    func(c *gin.Context) {
        c.Set(keyRequestId,rand.Int())
        c.Next()
    })
    r.GET("/ping", func(c *gin.Context) {
        h := gin.H{"message":"pong",}
        if rid,exist := c.Get(keyRequestId); exist{
            h[keyRequestId]=rid
        }
        c.JSON(200,h)
    })

    r.GET("/hello", func(c *gin.Context) {
        c.String(200,"hello")
    })
        //默認(rèn)8080端口
    r.Run()
}

restful路由

gin的路由來自httprouter庫。除“不支持路由正則表達(dá)式"之外,httprouter具有的功能,gin也具有:

func main(){
    router := gin.Default()
    
    router.GET("/user/:name", func(c *gin.Context) {
        name := c.Param("name")
        c.String(http.StatusOK, "Hello %s", name)
    })
}
  • 冒號 :

冒號:加上一個參數(shù)名組成路由參數(shù)??梢允褂?code>c.Params的方法讀取其值。這個值必須是字串string。諸如/user/rsj217,和user/hello都可以匹配,而/user//user/rsj217/不會被匹配。

下例中name代表":"的變量

func main(){
    router := gin.Default()
    
    router.GET("/user/:name", func(c *gin.Context) {
        name := c.Param("name")
        c.String(http.StatusOK, "Hello %s", name)
    })
}
  • 星號:*
    除了:,gin還提供了號處理參數(shù),號能匹配的規(guī)則就更多。

下例中action代表"*" 的變量

func main(){
    router := gin.Default()
    
    router.GET("/user/:name/*action", func(c *gin.Context) {
        name := c.Param("name")
        action := c.Param("action")
        message := name + " is " + action
        c.String(http.StatusOK, message)
    })
}
$  curl http://127.0.0.1:8000/user/carmen/
carmen is /%          
--                                                         
$  curl http://127.0.0.1:8000/user/carmen/中國
carmen is /中國%

文件上傳

  • 上傳單個文件
func main(){
    router := gin.Default()
    
    router.POST("/upload", func(c *gin.Context) {
        name := c.PostForm("name")
        fmt.Println(name)
        file, header, err := c.Request.FormFile("upload")
        if err != nil {
            c.String(http.StatusBadRequest, "Bad request")
            return
        }
        filename := header.Filename

        fmt.Println(file, err, filename)

        out, err := os.Create(filename)
        if err != nil {
            log.Fatal(err)
        }
        defer out.Close()
        _, err = io.Copy(out, file)
        if err != nil {
            log.Fatal(err)
        }
        c.String(http.StatusCreated, "upload successful")
    })
    router.Run(":8000")
}
  • 上傳多個文件
router.POST("/multi/upload", func(c *gin.Context) {
        err := c.Request.ParseMultipartForm(200000)
        if err != nil {
            log.Fatal(err)
        }

        formdata := c.Request.MultipartForm 

        files := formdata.File["upload"] 
        for i, _ := range files { /
            file, err := files[i].Open()
            defer file.Close()
            if err != nil {
                log.Fatal(err)
            }

            out, err := os.Create(files[i].Filename)

            defer out.Close()

            if err != nil {
                log.Fatal(err)
            }

            _, err = io.Copy(out, file)

            if err != nil {
                log.Fatal(err)
            }

            c.String(http.StatusCreated, "upload successful")

        }

    })

表單上傳與gin的render模板

  • 表單如下:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>upload</title>
</head>
<body>
<h3>Single Upload</h3>
<form action="/upload", method="post" enctype="multipart/form-data">
    <input type="text" value="hello gin" />
    <input type="file" name="upload" />
    <input type="submit" value="upload" />
</form>


<h3>Multi Upload</h3>
<form action="/multi/upload", method="post" enctype="multipart/form-data">
    <input type="text" value="hello gin" />
    <input type="file" name="upload" />
    <input type="file" name="upload" />
    <input type="submit" value="upload" />
</form>

</body>
</html>
  • 后端代碼
type User struct {
    Username string `form:"username" json:"username" binding:"required"`
    Passwd   string `form:"passwd" json:"passwd" bdinding:"required"`
    Age      int    `form:"age" json:"age"`
}

func main(){
    router := gin.Default()
    
    router.POST("/login", func(c *gin.Context) {
        var user User
        var err error
        contentType := c.Request.Header.Get("Content-Type")

        switch contentType {
        case "application/json":
            err = c.BindJSON(&user)
        case "application/x-www-form-urlencoded":
            err = c.BindWith(&user, binding.Form)
        }

        if err != nil {
            fmt.Println(err)
            log.Fatal(err)
        }

        c.JSON(http.StatusOK, gin.H{
            "user":   user.Username,
            "passwd": user.Passwd,
            "age":    user.Age,
        })

    })

}

middleware中間件

  • golang的net/http設(shè)計的一大特點就是特別容易構(gòu)建中間件。gin也提供了類似的中間件。
  • 中間件分為全局中間件,單個路由中間件和群組中間件。
  • 對于分組路由,嵌套使用中間件,可以限定中間件的作用范圍。
  • 需要注意的是中間件只對注冊過的路由函數(shù)起作用。
中間件實例
  • 鑒權(quán)
    router.GET("/auth/signin", func(c *gin.Context) {
        cookie := &http.Cookie{
            Name:     "session_id",
            Value:    "123",
            Path:     "/",
            HttpOnly: true,
        }
        http.SetCookie(c.Writer, cookie)
        c.String(http.StatusOK, "Login successful")
    })

    router.GET("/home", AuthMiddleWare(), func(c *gin.Context) {
        c.JSON(http.StatusOK, gin.H{"data": "home"})
    })

登錄函數(shù)會設(shè)置一個session_id的cookie,注意這里需要指定path為/,不然gin會自動設(shè)置cookie的path為/auth,一個特別奇怪的問題。/home的邏輯很簡單,使用中間件AuthMiddleWare注冊之后,將會先執(zhí)行AuthMiddleWare的邏輯,然后才到/home的邏輯。

func AuthMiddleWare() gin.HandlerFunc {
    return func(c *gin.Context) {
        if cookie, err := c.Request.Cookie("session_id"); err == nil {
            value := cookie.Value
            fmt.Println(value)
            if value == "123" {
                c.Next()
                return
            }
        }
        c.JSON(http.StatusUnauthorized, gin.H{
            "error": "Unauthorized",
        })
        c.Abort()
        return
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 一、gin簡介 Gin 是一個用 Go (Golang) 編寫的 HTTP web 框架。 它是一個類似于 mar...
    Every_dawn閱讀 2,625評論 1 4
  • 所謂框架 框架一直是敏捷開發(fā)中的利器,能讓開發(fā)者很快的上手并做出應(yīng)用,甚至有的時候,脫離了框架,一些開發(fā)者都不會寫...
    人世間閱讀 217,085評論 11 242
  • Gin是一個用Go語言編寫的web框架。它是一個類似于martini但擁有更好性能的API框架, 由于使用了htt...
    雪上霜閱讀 1,737評論 0 1
  • 本來自己打算繼續(xù)學(xué)下beanFactory源碼的,但是放假了自己也沒什么精神,看源碼又要求注意力很集中,所以想著看...
    me_2f11閱讀 1,364評論 1 1
  • 表情是什么,我認(rèn)為表情就是表現(xiàn)出來的情緒。表情可以傳達(dá)很多信息。高興了當(dāng)然就笑了,難過就哭了。兩者是相互影響密不可...
    Persistenc_6aea閱讀 129,566評論 2 7

友情鏈接更多精彩內(nèi)容