【第三届青训营-后端专场】课后作业 -《HTTP 框架修炼之道》

659 阅读2分钟

大家直接在评论区发布答案就可以哦~

课后作业-重点内容 Review

作业要求:

  1. 为什么 HTTP 框架做要分层设计?分层设计有哪些优势与劣势。
  1. 现有开源社区 HTTP 框架有哪些优势与不足。
  1. 中间件还有没有其他实现方式?可以用伪代码说明。
  1. 完成基于前缀路由树的注册与查找功能?可以用伪代码说明。
  1. 路由还有没有其他的实现方式?

    < 作业提交截止时间:5月24日 10:00前 >

正确答案:

该问题为开放性问题,答案合理即可。

  1. 优势:

    1. 分层设计可以提高框架的扩展性、可维护性、复用性
    2. 分层设计可以让相关同学聚焦在核心层上而不用关心其他层的实现
    3.   劣势:
    4. 提高代码设计的复杂性,设计不好可能会导致循环依赖
    5. 由于使用接口进行解耦,可能会对代码性能造成影响
  1. gin:易用性强;生态丰富,但扩展性一般,性能一般。

    1.   fasthttp:性能强;扩展性一般,生态一般。
    2.   go-zero:开箱即用,提供全套微服务能力,但扩展性一般,性能一般。
  1. 课程中讲的中间件模型需要有一个地方保存 index,对于没有 index 的场景,可以将中间件构造为递归函数进行调用。
// Endpoint represent one method for calling from remote.
type Endpoint func ( ctx context.Context, req, resp interface {})  ( err error )

// Middleware deal with input Endpoint and output Endpoint.
type Middleware func ( Endpoint ) Endpoint

// Chain connect middlewares into one middleware.
func chain ( mws ...Middleware ) Middleware {
return func ( next Endpoint ) Endpoint {
for i := len ( mws ) - 1; i >= 0; i-- {
next = mws [ i ]( next )
}
return next
   }
} 
  1. 伪代码如下,可以使用递归实现,也可以使用其他更高性能的实现,这里提供递归的实现方式。
func ( r *router ) addRoute ( path string, h app.HandlersChain ) {
// 检查 path 合理性
   checkPathValid ( path )
// 循环添加 path 中的每一段
   for i range len ( path ) {
// 处理 : 类型参数路由
      if path [ i ] == ":" {
// 添加 : 之前的静态路由
         Insert ( path [ :i ] , staticKind, nil )
// 处理参数名称
         paramNames.add ( paramName )
// 判断当前是否是路由 path 的最后一段
         if last {
// 插入最后一段
            Insert ( path [ i: ] , paramKind, handler )
return
         } else {
// 不是最后一段,插入该段后继续插入之后的部分。
            Insert ( path [ i: ] , paramKind, nil )
}
// 处理 * 号类型参数路由
      } else if path [ i ] == "*" {
// 添加 * 路由之前的部分
         Insert ( path [ :i ] , staticKind, nil )
// 处理参数名称
         paramNames.add (paramName)
// 添加最后一段
         Insert ( path [ i: ] , allKind, handler )
return
      }
}
// 添加最后的静态路由
   Insert ( path [ i: ] , staticKind, handler )
}

func find ( path string )  () {
   // 匹配静态路由
   if matchStaticKind {
nextSearchPath = handleStaticKind ( path, node )
path = nextSearchPath
   }
// 匹配 param 路由
   if matchParamKind {
nextSearchPath = handleParamKind ( path, node )
path = nextSearchPath
   }
// 匹配 * 路由
   if matchAllKind {
nextSearchPath = handleAllKind ( path, node )
path = nextSearchPath
   }
// 判断是否找到
   if endcondition {
return
   }

// 递归搜索下一段静态路由
   for node := range allStaticKindNodeChildren {
if prefixMatch {
node.find ( path )
}
}
// 搜索下一段 param 路由
   if node.HasParamKindChild {
node.find ( path)
   }
// 搜索下一段 * 路由
   if node.HasAllKindChild {
node.find ( path)
   }
return
} 
  1. 可以尝试使用正则匹配的方式注册路由