设为首页 收藏本站
查看: 1223|回复: 0

[经验分享] golang自定义路由控制实现(二)

[复制链接]

尚未签到

发表于 2018-9-21 06:20:53 | 显示全部楼层 |阅读模式
      先简单回顾一下在上一篇的文章中,上一篇我主要是结合了数组和Map完成路由映射,数组的大小为8,下标为0的代表Get方法,以此类推,而数组的值则是Map,键为URL,值则是我们编写对应的接口。但是上篇的设计仍存在着不足,主要是无法很好的面向RESTFUL设计,同时,我希望还能够希望一个功能,类似于SpringMVC中,可以将@Controller作用于类上,代表着该类下所有接口的一个起始路径。因此,本篇文章主要是讲解如何实现以上提到的两个功能。即面向RESTFUL以及流式注册接口。下面先看效果代码。
  

    o := odserver.Default()  o.Start("/main").
  Target("/test/").Get(HelloServer).Post(HelloServer).Delete(HelloServer).And().
  Target("/test2").Get(HelloServer2)
  o.Start("/{test}/main/").Target("/number/{number}").
  Get(HelloServer3).Post(HelloServer4)
  

  http.ListenAndServe(":8080",o)
  

func HelloServer3(c *odserver.Context) {  

  fmt.Fprint(c.Rw, c.Params)
  
}
  

      首先第一点的是,我们要如何将客户端访问的URL,准确的映射到含有占位符的接口。原理其实也不难,这里也主要简化了一下:即利用正则表达式,将接口路径中的参数转换成\w*。以/{test}/main/number/{number}为例子,转换结果为/\w*/main/number/\w*,通过正则表达式匹配则可以匹配到相对应的接口函数。
  
    第二点,如何实现流式注册接口。
  

o.Start("/main").  
Target("/test/").Get(HelloServer).Post(HelloServer).Delete(HelloServer).And().
  
Target("/test2").Get(HelloServer2)
  

      这里的设计主要是考虑到RESTFUL的知识,即URL描述的是资源,而Http Method描述的才是动作,所以大多数情况下,按照RESTFUL的规范是会出现URL相同但是Http Method不同。因此,这里的设计比起上一篇中的设计要做进一步重构:先匹配路径,再匹配方法(上一篇的设计是先匹配方法,再匹配路径)
  
    第一步我们自然想到要设计一个map,键是URL,但是值该如何设计,而值的主要目标是匹配方法,以及拥有其他属性能够进行额外的功能开发,即下面的HandlerObject。我的设计如下,详情看注释。
  

type FuncObject struct {  params []string
  
//对应编写的接口,IHandlerFunc只是个空接口
  f      IHandlerFunc
  exist  bool
  *httpConfig
  
}
  
//方法函数映射,0代表GET方法下的接口
  
type methodFuncs []FuncObject
  
/**
  关键struct,代表每个实体的请求
  */
  
type HandlerObject struct {
  *Router
  //对应占位符的参数
  params    []string
  //对该请求的http配置
  *httpConfig
  //请求路径 即start+target的路径
  path        string
  startPath   string
  
//方法函数映射
  methodFuncs methodFuncs
  
}
  

      上面HandlerObject出现了对Router的引用,Router相当于路由控制中心,他持有map[string]*HandlerObject。
  

func NewRouter() *Router {  return &Router{
  handler:   make(map[string]*HandlerObject),
  regexpMap: make(map[*regexp.Regexp]*HandlerObject),
  }
  
}
  

  
type Router struct {
  handler
  regexpMap
  
}
  

      这里有个问题,regexpMap作用是什么,相信仔细看的读者内心应该有答案了,没错,这里对应的是匹配正则路径的Map。但是还有一个问题是,我怎么知道当前请求的路径,是精准匹配还是模糊匹配。这里就要利用到Go中的协程和通道了,设置一个无缓冲的通道,对精准匹配和模糊匹配分别开启一条协程,哪个协程先匹配到,则往通道中传送对应的值,这样就能保证到无论是精准匹配和模糊匹配,我们最终都会且仅获取到一个值。同时对通道设置超时处理,如若超时,则认为是404情况。
  

func (r *Router) doUrlMapping(url string, method int) (*HandlerObject,bool) {  ch := make(chan *HandlerObject)
  //精准匹配
  go func() {
  if ho, ok := r.handler[url]; ok {
  ch

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-599015-1-1.html 上篇帖子: golang解析json报错:invalid character '\x00' after top-level value 下篇帖子: golang项目git-subtree完美解决差异包管理
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表