快捷搜索:  汽车  科技

go接口具体用途:Go框架解析iris

go接口具体用途:Go框架解析iris构建路由handler&启动http server:初始化一个http.server上图是我在读iris代码时,整理的iris框架的一个生命周期流程图,内容比较多。总的来说划分为四个大的部分:初始化iris.Application:注册路由到app.APIBuilder

在读这篇文章之前,如果没看过Go框架解析:beego的可以先去看看,因为Go框架解析:beego有讲关于 go如何启动一个http Server 这个知识点对理解本篇文章有很大的帮助。

安装

使用glide安装:

glide get github.com/kataras/iris glide get github.com/kataras/golog

启动一个简单的iris http服务:

//main.go package main import "github.com/kataras/iris" func main() { app := iris.Default() app.Get("/ping" func(ctx iris.Context) { ctx.JSON(iris.Map{ "message": "pong" }) }) app.Run(iris.Addr(":8888")) } iris的生命周期

go接口具体用途:Go框架解析iris(1)

访问图片源地址查看大图 http://cdn.tigerb.cn/20190628234814.png

上图是我在读iris代码时,整理的iris框架的一个生命周期流程图,内容比较多。总的来说划分为四个大的部分:

橙色部分

初始化iris.Application:

  • 创建iris.Application
  • 创建apiBuilder(app.Get()等方法的路由都是注册到这里)
  • 创建router(每个http请求都是通过router处理的)
蓝色部分

注册路由到app.APIBuilder

紫色部分

初始化一个http.server

绿色部分

构建路由handler&启动http server:

  • 注册 app.APIBuilder 到 app.Router.routesProvider
  • 注册 app.APIBuilder.routes 的路由到 app.Router.RequestHandler
  • 启动http server
关键代码解析
  1. 创建一个iris Application

// Application 首先看看我们的iris Application结构体组成 type Application struct { // 我们的路由都注册到了 APIBuilder *router.APIBuilder // *router.Router 实现了ServeHTTP方法 并且最终赋值给了&http.server{}.Handler *router.Router // 请求上下文池子 ContextPool *context.Pool // 配置项 config *Configuration // 日志 logger *golog.Logger // 视图 view view.View // 执行一次的once once sync.Once // 互斥锁 mu sync.Mutex Hosts []*host.Supervisor hostConfigurators []host.Configurator } // 创建了一个iris应用实例 // 为什么不直接New呢? // 因为Default里面注册了两个handle // 1. recover panic的方法, // 2. 请求日志 app := iris.Default() func Default() *Application { app := New() // 合成复用*APIBuilder的Use app.Use(recover.New()) // 合成复用*APIBuilder的Use app.Use(requestLogger.New()) return app } // app := New() 得到的结构体 app := &Application{ config: &config logger: golog.Default // 很关键:我们的路由都注册到了 APIBuilder APIBuilder: router.NewAPIBuilder() // 很关键:*router.Router 实现了ServeHTTP方法 并且最终赋值给了&http.server{}.Handler Router: router.NewRouter() } // 注册api请求的中间件 func (api *APIBuilder) Use(handlers ...context.Handler) { api.middleware = append(api.middleware handlers...) }

  1. 关于 router.NewAPIBuilder()

APIBuilder的routes属性很关键,最终的我们定义的路由都是注册到了这里。

// APIBuilder api := &APIBuilder{ macros: macro.Defaults errorCodeHandlers: defaultErrorCodeHandlers() reporter: errors.NewReporter() relativePath: "/" // 最终的我们定义的路由都是注册到了这里 routes: new(repository) } // repository的结构 type repository struct { routes []*Route }

结论:用户路由注册到了 app.APIBuilder.routes

  1. 关于 router.NewRouter()

router.NewRouter() 返回的是一个 &Router{} 指针, &Router{} 有三个很关键的属性和一个 ServeHTTP 成员方法。

三个关键的属性:

mainHandler http.HandlerFunc requestHandler RequestHandler routesProvider RoutesProvider

我们再看成员方法 ServeHTTP 实现了 ServeHTTP(w http.ResponseWriter r *http.Request) 方法,就是accept请求之后就会执行这个方法,我们看看具体方法内容。

// implement ServeHTTP func (router *Router) ServeHTTP(w http.ResponseWriter r *http.Request) { // 所以这里可以看出accept请求之后会执行mainHandler router.mainHandler(w r) }

func NewRouter() *Router { return &Router{} } type Router struct { mu sync.Mutex requestHandler RequestHandler // 每次http请求都会执行mainHandler mainHandler http.HandlerFunc wrapperFunc func(http.ResponseWriter *http.Request http.HandlerFunc) cPool *context.Pool r routesProvider RoutesProvider } // implement ServeHTTP func (router *Router) ServeHTTP(w http.ResponseWriter r *http.Request) { // 每次http请求都会执行mainHandler router.mainHandler(w r) }

结论:每次http请求都会执行 mainHandler

  1. 注册路由

这里很简单了就是注册用户路由到 app.APIBuilder.routes

//router func (api *APIBuilder) Get(relativePath string handlers ...context.Handler) *Route { return api.Handle(http.methodGet relativePath handlers...) } route := &Route{ Name: defaultName Method: method methodBckp: method Subdomain: subdomain tmpl: tmpl Path: path Handlers: handlers MainHandlerName: mainHandlerName FormattedPath: formattedPath }

  1. 构建请求handler

//启动路由 app.Run() :arrow_down: // 构建 app.Build() :arrow_down: // 构建路由 app.Router.BuildRouter(app.ContextPool routerHandler app.APIBuilder false) :arrow_down: // 构建请求Handler // 把app.APIBuilder注册的api注册到了requestHandler里 // 因为我们在下面发现请求都是从router.requestHandler去处理的 requestHandler.Build(routesProvider) :arrow_down: // 赋值 router.requestHandler = requestHandler router.routesProvider = routesProvider :arrow_down: // the important 没错很重要的地方mainHandler被赋值的地方 // 也就是accpet请求实际执行的代码 // 真相就在这 // the important router.mainHandler = func(w http.ResponseWriter r *http.Request) { // 构建请求上下文 ctx := cPool.Acquire(w r) // 处理请求 router.requestHandler.HandleRequest(ctx) // 释放请求上下文 cPool.Release(ctx) } :arrow_down: // 实际处理请求饿地方 // 路由的匹配就是这里了 func (h *routerHandler) HandleRequest(ctx context.Context)

  1. 启动HTTP Server

最后我们就是启动这个http server了,这里和绝大多数golang的http服务启动基本一致。

// 赋值http服务的ip port iris.Addr(":8888") :arrow_down: //创建http.Server并启动服务的匿名方法 func Addr(addr string hostConfigs ...host.Configurator) Runner { return func(app *Application) error { return app.NewHost(&http.Server{Addr: addr}). Configure(hostConfigs...). ListenAndServe() } } :arrow_down: // app.NewHost(&http.Server{Addr: addr}) // 就是这里赋值app.Router给http.Server的Handler的 if srv.Handler == nil { srv.Handler = app.Router } :arrow_down: // 启动服务 su.Server.Serve(l) :arrow_down: // accept请求 l.Accept() :arrow_down: // 启动一个goroutine处理请求 go c.serve(ctx) :arrow_down: // 最终至此真相都大白了 serverHandler{c.server}.ServeHTTP(w w.req) 结语

最后我们再简单的回顾下上面的流程:

go接口具体用途:Go框架解析iris(2)

猜您喜欢: