go學習筆記——gin框架

tonglin0325發表於2024-05-09

gin是一款輕量級的go web開發框架,官方文件

https://gin-gonic.com/docs/examples/

1.gin web專案結構

參考

https://github.com/voyagegroup/gin-boilerplate

gin+protobuf wire參考

https://github.com/mohuishou/blog-code/tree/main/01-go-training/04-project/10-layout

2.gin web quick start

https://gin-gonic.com/docs/quickstart/

在官方文件中提供了2個quick start的demo,一個稍微複雜,一個比較簡單

簡單的例子如下,建立一個/ping介面,返回pong

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
}

3.路由分組

如果gin專案的介面比較多的話,可以使用路由分組

https://gin-gonic.com/docs/examples/grouping-routes/

參考:【Go】基於 Gin 從0到1搭建 Web 管理後臺系統後端服務(三)路由、自定義校驗器和 Redis

4.資料繫結

將請求的引數傳遞給介面中的變數,需要使用gin的資料繫結

如果是path parameter

使用c.Param("name")

https://gin-gonic.com/docs/examples/param-in-path/

使用c.ShouldBindUri(&person)

https://gin-gonic.com/docs/examples/bind-uri/

如果是query parameter或者post請求的form-data

使用c.ShouldBind(&user)

https://gin-gonic.com/docs/examples/bind-query-or-post/

5.統一的response

可以如下定義統一的介面response,其中的interface{}類似java中的泛型T

type ControllerResponse struct {
	Code int
	Msg  string
	Data interface{}
}

func Response(ctx *gin.Context, code int, msg string, data interface{}) {
	resp := ControllerResponse{Code: code, Msg: msg, Data: data}
	ctx.JSON(code, resp)
	ctx.Abort()
}

func Success(ctx *gin.Context, msg string, data interface{}) {
	Response(ctx, 200, msg, data)
}

func Fail(ctx *gin.Context, msg string, data interface{}) {
	Response(ctx, 500, msg, data)
}

參考:go語言web開發系列之十五:gin框架統一定義API錯誤碼

6.middleware中介軟體

1.使用middleware

下面定義了3個middleware

// MiddleWare1 定義中介軟體1
func MiddleWare1() gin.HandlerFunc {
	return func(c *gin.Context) {
		fmt.Println("前 m1")
		c.Next()
		fmt.Println("後 m1")
	}
}

// MiddleWare2 定義中介軟體2
func MiddleWare2() gin.HandlerFunc {
	return func(c *gin.Context) {
		fmt.Println("前 m2")
		c.Next()
		fmt.Println("後 m2")
	}
}

// MiddleWare3 定義中介軟體3
func MiddleWare3() gin.HandlerFunc {
	return func(c *gin.Context) {
		fmt.Println("前 m3")
		c.Next()
		fmt.Println("後 m3")
	}
}

在gin中新增middleware

func main() {
   // 建立路由
   engine := gin.Default()

   // 註冊中介軟體
   engine.Use(MiddleWare1(), MiddleWare2(), MiddleWare3())

   // 路由規則
   engine.GET("/ping", func(c *gin.Context) {
      fmt.Println("hello world")
      c.JSON(200, gin.H{"msg": "pong"})
   })
   err:=engine.Run(":3000")
   if err != nil {
      fmt.Println(err)
   }
}

輸出如下

前 m1
前 m2
前 m3
hello world
後 m3
後 m2
後 m1
[GIN] 2023/12/25 - 00:06:11 | 200 |      35.726µs |       127.0.0.1 | GET      "/ping"

介面返回pong

2.Next()和Abort()

Next()之前的程式碼會在執行HandlerFunc之前執行,之後的程式碼會在執行HandlerFunc之後執行

如果將middleware2中的c.Next()修改成c.Abort()

// MiddleWare2 定義中介軟體2
func MiddleWare2() gin.HandlerFunc {
	return func(c *gin.Context) {
		fmt.Println("前 m2")
		c.Abort()
		fmt.Println("後 m2")
	}
}

則輸出將會如下

前 m1
前 m2
後 m2
後 m1
[GIN] 2023/12/25 - 00:11:05 | 200 |      16.262µs |       127.0.0.1 | GET      "/ping"

介面無返回

可以Abort()不會阻止當前middleware的執行,但是會中止下游middleware以及HandlerFunc的執行

參考:[Go Package] gin 中介軟體流程控制:c.Next() / c.Abort()

相關文章