大家直接在评论区发布答案就可以哦~
课后作业-重点内容 Review
作业要求:
- 为什么 HTTP 框架做要分层设计?分层设计有哪些优势与劣势。
- 现有开源社区 HTTP 框架有哪些优势与不足。
- 中间件还有没有其他实现方式?可以用伪代码说明。
- 完成基于前缀路由树的注册与查找功能?可以用伪代码说明。
-
路由还有没有其他的实现方式?
< 作业提交截止时间:5月24日 10:00前 >
正确答案:
该问题为开放性问题,答案合理即可。
-
优势:
- 分层设计可以提高框架的扩展性、可维护性、复用性
- 分层设计可以让相关同学聚焦在核心层上而不用关心其他层的实现
- 劣势:
- 提高代码设计的复杂性,设计不好可能会导致循环依赖
- 由于使用接口进行解耦,可能会对代码性能造成影响
-
gin:易用性强;生态丰富,但扩展性一般,性能一般。
- fasthttp:性能强;扩展性一般,生态一般。
- go-zero:开箱即用,提供全套微服务能力,但扩展性一般,性能一般。
- 课程中讲的中间件模型需要有一个地方保存 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
}
}
- 伪代码如下,可以使用递归实现,也可以使用其他更高性能的实现,这里提供递归的实现方式。
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
}
- 可以尝试使用正则匹配的方式注册路由