相思资源网 Design By www.200059.com

前言

本文主要介绍了关于golang实现路由调度的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧

项目地址

github (本地下载)

本项目依赖

使用标准库实现,无额外依赖

为什么需要路由调度层

golang http标准库只能精确匹配请求的URI,然后执行handler。现在一般web项目都至少有个Controller层,以struct实现,根据不同的请求路径派发到不同的方法中去。

路由调度器定义

由于golang暂时还不可以动态创建对象(比如java的Class.forName("xxx").newInstance(),xxx是任意存在的class名称)。所以需要手动注册一下controller关系。

  1. 定义routes保存controller指针
  2. 解析请求过来的URL查询参数,暂定a为action名称,c为controller名称,本文偷了下懒,没对PATH_INFO做处理,也没有对actionName的首字母自动大写,这个不影响本文要传达的核心内容,有兴趣的读者可以自行实现。
  3. 根据URL中的controllerName找到对应的controller
  4. 使用反射将当前请求对象的*http.Request和http.ResponseWriter设置到该Controller
  5. 使用反射以及actionName对应该controller的方法

由于golang的继承不是一般的OOP,所以也没有父子类这种说法,路由注册那里只能使用interface{}

代码实现

app/app.go

该文件为核心调度文件

package app

import (
 "net/http"
 "reflect"
 "fmt"
)

type application struct {
 routes map[string]interface{}
}

func New() *application {
 return &application{
  routes: make(map[string]interface{}),
 }
}

func (p *application) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 controllerName := r.URL.Query().Get("c")
 actionName := r.URL.Query().Get("a")
 if controllerName == "" || actionName == "" {
  http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
  return
 }
 route, ok := p.routes[controllerName]
 if !ok {
  http.Error(w, "Controller Not Found", http.StatusNotFound)
  return
 }
 ele := reflect.ValueOf(route).Elem()
 ele.FieldByName("Request").Set(reflect.ValueOf(r))
 ele.FieldByName("Response").Set(reflect.ValueOf(w))
 ele.MethodByName(actionName).Call([]reflect.Value{})
}

func (p *application) printRoutes() {
 for route, controller := range p.routes {
  ele := reflect.ValueOf(controller).Type().String()
  fmt.Printf("%s %s\n", route, ele)
 }
}

func (p *application) Get(route string, controller interface{}) {
 p.routes[route] = controller
}

func (p *application) Run(addr string) error {
 p.printRoutes()
 fmt.Printf("listen on %s\n", addr)
 return http.ListenAndServe(addr, p)
}

app/controller.go

控制器"基类"

package app

import "net/http"

type Controller struct {
 Response http.ResponseWriter
 Request *http.Request
}

controller/site.go

具体业务逻辑类

package controllers

import (
 "fmt"
 "app"
)

type SiteController struct {
 app.Controller
}

func (p SiteController) Index() {
 fmt.Fprint(p.Response, p.Request.RequestURI)
}

main.go

入口文件

package main

import (
 _ "github.com/go-sql-driver/mysql"
 "app"
 "controllers"
)

func main() {
 application := app.New()
 application.Get("site", &controllers.SiteController{})
 application.Run(":8080")
}

运行项目

启动进程

访问http://localhost:8080"color: #ff0000">写在最后

希望这个小小的项目能启发到各位读者,早日开发出适合自己的Web框架!

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。

标签:
golang调度,golang,反射,路由,golang协程调度

相思资源网 Design By www.200059.com
广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
相思资源网 Design By www.200059.com

评论“golang利用不到20行代码实现路由调度详解”

暂无golang利用不到20行代码实现路由调度详解的评论...

《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线

暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。

艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。

《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。