天天看點

Gin源碼閱讀(一)

一個躺平程式員的回光返照,内容大部分是有道翻譯小部分是百度内容,如果有錯誤請在評論區提出,馬上改

直接貼代碼

// 設定運作模式 有三個值可選debug, release, test
	gin.SetMode(utils.AppMode)
	// 擷取架構引擎
	r :=gin.Default()
	
	// 自定義方法,綁定路由方法
	initAdminRouter(r)
	initMobileRouter(r)
	// 運作
	r.Run(":" + utils.HttpPort)
           

gin.SetMode

// SetMode sets gin mode according to input string.
// SetMode根據輸入字元串設定gin模式。
func SetMode(value string) {
	if value == "" {
		value = DebugMode
	}

	switch value {
		case DebugMode: // debug
			ginMode = debugCode
		case ReleaseMode: // release
			ginMode = releaseCode
		case TestMode: // test
			ginMode = testCode
		default:
			panic("gin mode unknown: " + value + " (available mode: debug release test)")
	}

	modeName = value
}
           

gin.Default()

debugPrintWARNINGDefault()

New()

Use()

Logger()

Recovery()

// Default returns an Engine instance with the Logger and Recovery middleware already attached.
// 預設傳回一個已經附加了Logger和Recovery中間件的引擎執行個體。
func Default() *Engine {
	// 驗證go的版本号是否符合gin所需最低版本 go1.12+
	debugPrintWARNINGDefault()
	// 擷取一個引擎執行個體, 擷取的是引用類型執行個體
	engine := New()
	// 引擎執行個體bind Logger 和Recover中間件
	engine.Use(Logger(), Recovery())
	// 傳回執行個體
	return engine
}
           

debugPrintWARNINGDefault

// ginSupportMinGoVer 預設值為 12
func debugPrintWARNINGDefault() {
	if v, e := getMinVer(runtime.Version()); e == nil && v <= ginSupportMinGoVer {
		debugPrint(`[WARNING] Now Gin requires Go 1.12+.

`)
	}
	debugPrint(`[WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.

`)
}

// 輸入版本号go1.16.2傳回大版本号 16
func getMinVer(v string) (uint64, error) {
	first := strings.IndexByte(v, '.')
	last := strings.LastIndexByte(v, '.')
	if first == last {
		return strconv.ParseUint(v[first+1:], 10, 64)
	}
	return strconv.ParseUint(v[first+1:last], 10, 64)
}
           

New

// 傳回一個引擎執行個體(引用類型)
func New() *Engine {
	// 提示資訊
	debugPrintWARNINGNew()
	// 擷取引擎執行個體
	engine := &Engine{
		// 初始化路由組
		RouterGroup: RouterGroup{
			// 路由組處理器
			Handlers: nil,
			basePath: "/",
			root:     true,
		},
		FuncMap:                template.FuncMap{},
		// 如果目前路由不能比對,但存在帶(不帶)尾斜杠的路徑處理程式,則啟用自動重定向。例如,如果/foo/被請求,但是/foo的路由隻存在,用戶端被重定向到/foo, GET請求的狀态碼是301,其他所有請求方法的狀态碼是307
		RedirectTrailingSlash:  true,
		RedirectFixedPath:      false,
		HandleMethodNotAllowed: false,
		//如果啟用,用戶端IP将從請求頭中解析,比對存儲在' (*gin.Engine). remoteipheaders '。
		//如果沒有擷取IP,則傳回到從' (*gin.Context). request . remoteaddr '中擷取的IP。
		ForwardedByClientIP:    true,
		// 啟用擷取用戶端IP(ForwardedByClientIP為true)且通過(TrustedProxies)時擷取指定頭部資訊。
		RemoteIPHeaders:        []string{"X-Forwarded-For", "X-Real-IP"},
		TrustedProxies:         []string{"0.0.0.0/0"},
		// defaultAppEngine預設為false
		AppEngine:              defaultAppEngine,
		// 啟用RawPath
		UseRawPath:             false,
		RemoveExtraSlash:       false,
		// 如果為true,則不轉義路徑值。如果UseRawPath為false(預設情況下),則UnescapePathValues有效為true,如url.Path會被使用,它已經沒有轉義。
		UnescapePathValues:     true,
		// 配置設定最大上傳大小 預設為32MB 32<<20
		MaxMultipartMemory:     defaultMultipartMemory,
		// 建立長度為0的methodTrees切片且預留9個存儲空間
		trees:                  make(methodTrees, 0, 9),
		// 定義預設定界符
		delims:                 render.Delims{Left: "{{", Right: "}}"},
		secureJSONPrefix:       "while(1);",
	}
	// 将初始化完成的引擎執行個體指派
	engine.RouterGroup.engine = engine
	/**
	定義對象池(大概)并賦予預設值(大概,源碼中為)
		if x == nil && p.New != nil {
			x = p.New()
		}
		return x
	*/
	engine.pool.New = func() interface{} {
		return engine.allocateContext()
	}
	return engine
}

// 配置設定Context(上下文) 傳回 Context(引用)
func (engine *Engine) allocateContext() *Context {
	/**
	Params為 []type Param struct {
		Key   string
		Value string
	}
	engine.maxParams 預設為0
	*/
	v := make(Params, 0, engine.maxParams)
	return &Context{engine: engine, params: &v}
}
           

Use

// Engine的Use方法,不定參,參數的類型為HandlerFunc 傳回IRoutes
func (engine *Engine) Use(middleware ...HandlerFunc) IRoutes {
	engine.RouterGroup.Use(middleware...)
	// 建構404請求 noRoute
	engine.rebuild404Handlers()
	// 建構405請求 noMethod
	engine.rebuild405Handlers()
	return engine
}
// RouteGroup.Use
// 在RouteGroup中添加處理程式(中間件) IRoutes
func (group *RouterGroup) Use(middleware ...HandlerFunc) IRoutes {
	// Handlers是Group中的處理程式存儲屬性
	group.Handlers = append(group.Handlers, middleware...)
	return group.returnObj()
}
           

Logger

// 剛看到這兒的時候我還在想他是怎麼實作的 HandlerFunc定義為 type HandlerFunc func(*Context),看完代碼發現我是真的蠢
// 傳回一個HandlerFunc
func Logger() HandlerFunc {
	return LoggerWithConfig(LoggerConfig{})
}

// LoggerWithConfig instance a Logger middleware with config.
// LoggerWithConfig執行個體是一個帶有config的Logger中間件。
// 傳回值是一個HandleFunc
func LoggerWithConfig(conf LoggerConfig) HandlerFunc {
	// 代碼略過,架構主體走完在看這些中間件具體實作
	// ...
	
	// 傳回一個匿名方法 666 果然人與人之間是不一樣的
	return func(c *Context) {
	}
}
           

Recovery

func Recovery() HandlerFunc {
	return RecoveryWithWriter(DefaultErrorWriter)
}

// RecoveryWithWriter returns a middleware for a given writer that recovers from any panics and writes a 500 if there was one.
RecoveryWithWriter為給定的寫入器傳回一個中間件,該中間件可以從任何panics中恢複,如果有panics,則寫入一個500。
func RecoveryWithWriter(out io.Writer, recovery ...RecoveryFunc) HandlerFunc {
	// 如果傳了後續參數則使用,如果沒有則使用預設參, 預設參的一種實作方式
	if len(recovery) > 0 {
		return CustomRecoveryWithWriter(out, recovery[0])
	}
	return CustomRecoveryWithWriter(out, defaultHandleRecovery)
}

// CustomRecoveryWithWriter returns a middleware for a given writer that recovers from any panics and calls the provided handle func to handle it.
func CustomRecoveryWithWriter(out io.Writer, handle RecoveryFunc) HandlerFunc {
	var logger *log.Logger
	if out != nil {
		logger = log.New(out, "\n\n\x1b[31m", log.LstdFlags)
	}
	return func(c *Context) {
		// 延遲執行 最後執行, 如果多個defer則按棧的規則先進後出
		// 入 func(1) func(2) func(3)
		// 出 3 2 1     
		defer func() {
			// ...
		}()// 匿名方法立即執行方法
		// c為Context  Next()為繼續執行下一個處理方法(大概)
		c.Next()
	}
}
// c.Next() 将handlers中的方法依次執行
func (c *Context) Next() {
	c.index++
	for c.index < int8(len(c.handlers)) {
		c.handlers[c.index](c)
		c.index++
	}
}