Gin 框架 -二-: 服務啓動源碼分析

1. 啓動服務

1.1 服務源碼

package main
// 引入gin框架
import "github.com/gin-gonic/gin"
func main() {
 // 創建一個默認的路由引擎
 engine := gin.Default()
 // 註冊Get路由
 engine.GET("/", func(ctx *gin.Context) {
  ctx.JSON(200,gin.H{
   "msg":"請求成功",
  })
 })
  // 默認監聽的是 0.0.0.0:8080
 _ = engine.Run()
}

1.2 啓動輸出

 go run main.go 
[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    /                         --> main.main.func1 (3 handlers)
[GIN-debug] Environment variable PORT is undefined. Using port :8080 by default
[GIN-debug] Listening and serving HTTP on :8080

2. 代碼分析

2.1 import "github.com/gin-gonic/gin"

在引入Gin框架時,包內相關的init()方法都會被執行;經查找發現下面兩個init方法;

a. 第一個 init 方法

方法位置: github.com/gin-gonic/gin/context_appengine.go

package gin
func init() {
  // 設置AppEngine = true
 defaultAppEngine = true
}

b. 第二個 init 方法

方法位置: github.com/gin-gonic/gin/mode.go

func init() {
  // 設置服務的運行模式,默認是DebugMode
  // 分別有三種模式:DebugMode=0(開發模式)、releaseCode=1(生產模式)、testCode=2(測試模式)
 mode := os.Getenv(EnvGinMode)
 SetMode(mode)
}

2.2 gin.Default()

gin.Default 源碼如下:

func Default() *Engine {
  // 打印gin-debug信息
 debugPrintWARNINGDefault()
  // 新建一個無路由無中間的引擎
 engine := New()
  // 註冊全局日誌和異常捕獲中間件
 engine.Use(Logger(), Recovery())
 return engine
}

@注意: Gin 框架中註冊中間件是通過 engine.Use(xx) 的方式。 

2.3 engine.GET("/",...)

1. 源碼
// 註冊一個匹配路徑(relativePath)的Get請求路由
// handlers是對應的處理邏輯
func (group *RouterGroup) GET(relativePath string, handlers ...HandlerFunc) IRoutes {
 return group.handle(http.MethodGet, relativePath, handlers)
}

在上述示例代碼中我們註冊了一個匹配根目錄 ("/") 的路由,處理handlers是匿名函數, 直接調用ctx.JSON返回json格式的數據;

// 註冊Get路由
engine.GET("/", func(ctx *gin.Context) {
  ctx.JSON(200,gin.H{
    "msg":"請求成功",
  })
})
2. 多種返回格式

gin.Context支持多種返回格式, 整理常用的返回格式如下:

I5fBWG

3.Json、AsciiJSON、PureJSON 對比
package main
import "github.com/gin-gonic/gin"
func main() {
 // 創建一個默認的路由引擎
 engine := gin.Default()
 // 註冊Get路由
 engine.GET("/", func(ctx *gin.Context) {
  key, _ := ctx.GetQuery("key")
  msgBody := gin.H{
   "msg": "請求成功",
   "html":"<span>我是一段html代碼</span>",
  }
  switch key {
  case "1":
   msgBody["method"] = "ctx.JSON"
   ctx.JSON(200, msgBody)
  case "2":
   msgBody["method"] = "ctx.PureJSON"
   ctx.PureJSON(200, msgBody)
  case "3":
   msgBody["method"] = "ctx.AsciiJSON"
   ctx.AsciiJSON(200, msgBody)
  default:
   ctx.JSON(500, gin.H{
    "msg": "請求失敗",
   })
  }
  return
 })
 _ = engine.Run()
}

請求返回:

➜  ~ curl http://127.0.0.1:8080/\?key\=1
{"html":"\u003cspan\u003e我是一段html代碼\u003c/span\u003e","method":"ctx.JSON","msg":"請求成功"}%

➜  ~ curl http://127.0.0.1:8080/\?key\=2
{"html":"<span>我是一段html代碼</span>","method":"ctx.PureJSON","msg":"請求成功"}

➜  ~ curl http://127.0.0.1:8080/\?key\=3
{"html":"\u003cspan\u003e\u6211\u662f\u4e00\u6bb5html\u4ee3\u7801\u003c/span\u003e","method":"ctx.AsciiJSON","msg":"\u8bf7\u6c42\u6210\u529f"}%

總結

mbVb6Q

2.4 engine.Run()

1.Run源碼如下
func (engine *Engine) Run(addr ...string) (err error) {
  // 延遲關閉輸出ERROR類型的日誌信息
 defer func() { debugPrintError(err) }()
  // 設置CIDR(無類型域間路由)信息,默認返回: 0.0.0.0/0
 trustedCIDRs, err := engine.prepareTrustedCIDRs()
 if err != nil {
  return err
 }
 engine.trustedCIDRs = trustedCIDRs
  // 設置監聽IP和端口信息,默認是":8080"
 address := resolveAddress(addr)
 debugPrint("Listening and serving HTTP on %s\n", address)
  // 啓動服務
 err = http.ListenAndServe(address, engine)
 return
}
2. 爲什麼默認監聽是 ":8080"

Run方法中調用resolveAddress(addr), 該方法源碼如下:

// 接收一個字符串切片參數
func resolveAddress(addr []string) string {
  // 如果參數長度爲0,默認監聽8080
 switch len(addr) {
 case 0:
  if port := os.Getenv("PORT"); port != "" {
   debugPrint("Environment variable PORT=\"%s\"", port)
   return ":" + port
  }
  debugPrint("Environment variable PORT is undefined. Using port :8080 by default")
  return ":8080"
 case 1:
      // 如果參數長度爲1,監聽IP和端口
  return addr[0]
 default:
     //  如果參數長度大於1,則報錯
  panic("too many parameters")
 }
}
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/cP9IDQglrINehasD0L9waQ