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,则写入一个500func 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++
	}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值