Gin篇:Gin基礎

 

安裝Gin

1、配置代理

請查看:https://github.com/goproxy/goproxy.cn/blob/master/README.zh-CN.md

go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct

2、go get -u -v github.com/gin-gonic/gin

-v:打印出被構建的代碼包的名字
-u:已存在相關的代碼包,強行更新代碼包及其依賴包

3.部分包無法安裝

crypto無法下載解決方式:
1.進入$GOPATH(你的安裝go 的路徑)
2.進入 $GOPATH/src, 創建文件夾 golang.org, 以及子文件夾 golang.org/x
3.進$GOPATH/golang.org/x 使用如下命令:
4.git clone https://github.com/golang/crypto.git
protobuf無法下載解決方式:
1.進入$GOPATH(你的安裝go 的路徑)
2.進入 $GOPATH/src, 創建文件夾 google.golang.org,以及子文件google.golang.org/protobuf
3.將 google.golang.org/protobuf 包對應的github上的代碼下載下來,github地址:https://github.com/protocolbuffers/protobuf-go 
4.將下載下來的protobuf-go/目錄下的全部文件複製到 "google.golang.org/protobuf "中

  

第一個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(":8200") // listen and serve on 0.0.0.0:8200
}
  1. 首先,我們使用了gin.Default()生成了一個實例,這個實例即 WSGI 應用程序。
  2. 接下來,我們使用r.Get("/", ...)聲明瞭一個路由,告訴 Gin 什麼樣的URL 能觸發傳入的函數,這個函數返回我們想要顯示在用戶瀏覽器中的信息。
  3. 最後用 r.Run()函數來讓應用運行在本地服務器上,默認監聽端口是 8200,可以傳入參數設置端口,例如r.Run(":9999")即運行在 9999端口。
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.

[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
 - using env:	export GIN_MODE=release
 - using code:	gin.SetMode(gin.ReleaseMode)

[GIN-debug] GET    /ping                     --> main.main.func1 (3 handlers)
[GIN-debug] Listening and serving HTTP on :8000

 

 

 

 

 

路由(Route)

路由方法有 GET, POST, PUT, PATCH, DELETE 和 OPTIONS,還有Any,可匹配以上任意類型的請求。

func main() {
    // Disable Console Color
    // gin.DisableConsoleColor()

    // 使用默認中間件創建一個gin路由器
    // logger and recovery (crash-free) 中間件
    router := gin.Default()

    router.GET("/someGet", getting)
    router.POST("/somePost", posting)
    router.PUT("/somePut", putting)
    router.DELETE("/someDelete", deleting)
    router.PATCH("/somePatch", patching)
    router.HEAD("/someHead", head)
    router.OPTIONS("/someOptions", options)

    // 默認啓動的是 8080端口,也可以自己定義啓動端口
    router.Run()
    // router.Run(":3000") for a hard coded port
}

解析路徑參數

func main() {
    router := gin.Default()

    // 此規則能夠匹配/user/john這種格式,但不能匹配/user/ 或 /user這種格式
    router.GET("/user/:name", func(c *gin.Context) {
        name := c.Param("name")
        c.String(http.StatusOK, "Hello %s", name)
    })

    // 但是,這個規則既能匹配/user/john/格式也能匹配/user/john/send這種格式
    // 如果沒有其他路由器匹配/user/john,它將重定向到/user/john/
    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)
    })

    router.Run(":8080")
}

獲取Get參數

func main() {
    router := gin.Default()

    // 匹配的url格式:  /welcome?firstname=Jane&lastname=Doe
    router.GET("/welcome", func(c *gin.Context) {
        firstname := c.DefaultQuery("firstname", "Guest")
        lastname := c.Query("lastname") // 是 c.Request.URL.Query().Get("lastname") 的簡寫

        c.String(http.StatusOK, "Hello %s %s", firstname, lastname)
    })
    router.Run(":8080")
}

獲取Post參數

func main() {
    router := gin.Default()

    router.POST("/form_post", func(c *gin.Context) {
        message := c.PostForm("message")
        nick := c.DefaultPostForm("nick", "anonymous") // 此方法可以設置默認值

        c.JSON(200, gin.H{
            "status":  "posted",
            "message": message,
            "nick":    nick,
        })
    })
    router.Run(":8080")
}

Get + Post 混合

示例:
POST /post?id=1234&page=1 HTTP/1.1
Content-Type: application/x-www-form-urlencoded

name=manu&message=this_is_great
func main() {
    router := gin.Default()

    router.POST("/post", func(c *gin.Context) {

        id := c.Query("id")
        page := c.DefaultQuery("page", "0")
        name := c.PostForm("name")
        message := c.PostForm("message")

        fmt.Printf("id: %s; page: %s; name: %s; message: %s", id, page, name, message)
    })
    router.Run(":8080")
}
結果:id: 1234; page: 1; name: manu; message: this_is_great

路由分組

func main() {
    router := gin.Default()

    // Simple group: v1
    v1 := router.Group("/v1")
    {
        v1.POST("/login", loginEndpoint)
        v1.POST("/submit", submitEndpoint)
        v1.POST("/read", readEndpoint)
    }

    // Simple group: v2
    v2 := router.Group("/v2")
    {
        v2.POST("/login", loginEndpoint)
        v2.POST("/submit", submitEndpoint)
        v2.POST("/read", readEndpoint)
    }

    router.Run(":8080")
}

 

上傳文件

單個文件

r.POST("/upload1", func(c *gin.Context) {
	file, _ := c.FormFile("file")
	// c.SaveUploadedFile(file, dst)
	c.String(http.StatusOK, "%s uploaded!", file.Filename)
})

多個文件

r.POST("/upload2", func(c *gin.Context) {
	// Multipart form
	form, _ := c.MultipartForm()
	files := form.File["upload[]"]

	for _, file := range files {
		log.Println(file.Filename)
		// c.SaveUploadedFile(file, dst)
	}
	c.String(http.StatusOK, "%d files uploaded!", len(files))
})

  

中間件(Middleware)

// 作用於全局
r.Use(gin.Logger())
r.Use(gin.Recovery())

// 作用於單個路由
r.GET("/benchmark", MyBenchLogger(), benchEndpoint)

// 作用於某個組
authorized := r.Group("/")
authorized.Use(AuthRequired())
{
	authorized.POST("/login", loginEndpoint)
	authorized.POST("/submit", submitEndpoint)
無中間件啓動使用
r := gin.New()
// 默認啓動方式,包含 Logger、Recovery 中間件
r := gin.Default()
func main() {
    // 創建一個不包含中間件的路由器
    r := gin.New()

    // 全局中間件
    // 使用 Logger 中間件
    r.Use(gin.Logger())

    // 使用 Recovery 中間件
    r.Use(gin.Recovery())

    // 路由添加中間件,可以添加任意多個
    r.GET("/benchmark", MyBenchLogger(), benchEndpoint)

    // 路由組中添加中間件
    // authorized := r.Group("/", AuthRequired())
    // exactly the same as:
    authorized := r.Group("/")
    // per group middleware! in this case we use the custom created
    // AuthRequired() middleware just in the "authorized" group.
    authorized.Use(AuthRequired())
    {
        authorized.POST("/login", loginEndpoint)
        authorized.POST("/submit", submitEndpoint)
        authorized.POST("/read", readEndpoint)

        // nested group
        testing := authorized.Group("testing")
        testing.GET("/analytics", analyticsEndpoint)
    }

    // Listen and serve on 0.0.0.0:8080
    r.Run(":8080")
}

寫日誌文件

func main() {
    // 禁用控制檯顏色
    gin.DisableConsoleColor()

    // 創建記錄日誌的文件
    f, _ := os.Create("gin.log")
    gin.DefaultWriter = io.MultiWriter(f)

    // 如果需要將日誌同時寫入文件和控制檯,請使用以下代碼
    // gin.DefaultWriter = io.MultiWriter(f, os.Stdout)

    router := gin.Default()
    router.GET("/ping", func(c *gin.Context) {
        c.String(200, "pong")
    })

    router.Run(":8080")
} 

自定義日誌格式

func main() {
    router := gin.New()

    // LoggerWithFormatter 中間件會將日誌寫入 gin.DefaultWriter
    // By default gin.DefaultWriter = os.Stdout
    router.Use(gin.LoggerWithFormatter(func(param gin.LogFormatterParams) string {

        // 你的自定義格式
        return fmt.Sprintf("%s - [%s] \"%s %s %s %d %s \"%s\" %s\"\n",
                param.ClientIP,
                param.TimeStamp.Format(time.RFC1123),
                param.Method,
                param.Path,
                param.Request.Proto,
                param.StatusCode,
                param.Latency,
                param.Request.UserAgent(),
                param.ErrorMessage,
        )
    }))
    router.Use(gin.Recovery())

    router.GET("/ping", func(c *gin.Context) {
        c.String(200, "pong")
    })

    router.Run(":8080")
}

輸出:

::1 - [Fri, 07 Dec 2018 17:04:38 JST] "GET /ping HTTP/1.1 200 122.767µs "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.80 Safari/537.36" "

  

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章