当前位置: 首页 > 编程笔记 >

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

娄振
2023-03-14
本文向大家介绍golang利用不到20行代码实现路由调度详解,包括了golang利用不到20行代码实现路由调度详解的使用技巧和注意事项,需要的朋友参考一下

前言

本文主要介绍了关于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?c=site&a=Index会输出/?c=site&a=Index

写在最后

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

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

 类似资料:
  • 本文向大家介绍利用Spring Cloud Zuul实现动态路由示例代码,包括了利用Spring Cloud Zuul实现动态路由示例代码的使用技巧和注意事项,需要的朋友参考一下 前言 本文主要给大家介绍了关于Spring Cloud Zuul实现动态路由的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧。 Zuul 是提供动态路由,监控,弹性,安全等的边缘服务。Zuul

  • 本文向大家介绍AngularJs ng-route路由详解及实例代码,包括了AngularJs ng-route路由详解及实例代码的使用技巧和注意事项,需要的朋友参考一下 前提 首先需要在页面引入angular和angular-route,注意要在angular-route之前引入angular <script src="../../bower_components/angular/angular

  • 本文向大家介绍nodeJS实现路由功能实例代码,包括了nodeJS实现路由功能实例代码的使用技巧和注意事项,需要的朋友参考一下 前面的话 本文将使用NodeJS实现较复杂应用的路由功能 结构 项目结构如下 代码如下  功能 【router.js】 【404.html】 【about.html】 【home.html】 演示 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持呐喊教

  • 本文向大家介绍AngularJS中的路由使用及实现代码,包括了AngularJS中的路由使用及实现代码的使用技巧和注意事项,需要的朋友参考一下 前  言 本章节将为大家介绍 AngularJS 路由。AngularJS 路由允许我们通过不同的 URL 访问不同的内容。通过 AngularJS 可以实现多视图的单页Web应用(single page web application,SPA)。 1.1

  • 本文向大家介绍golang 40行代码实现通用协程池,包括了golang 40行代码实现通用协程池的使用技巧和注意事项,需要的朋友参考一下 代码仓库 goroutine-pool golang的协程管理 golang协程机制很方便的解决了并发编程的问题,但是协程并不是没有开销的,所以也需要适当限制一下数量。 不使用协程池的代码(示例代码使用chan实现,代码略啰嗦) 需要实现的需求有两个: 限制最

  • 本文向大家介绍利用Golang如何调用Linux命令详解,包括了利用Golang如何调用Linux命令详解的使用技巧和注意事项,需要的朋友参考一下 本文介绍的是Golang使用 os/exec 来执行 Linux 命令,分享出来供大家参考学习,下面来看看详细的介绍: 下面是一个简单的示例: 或者创建一个缓冲读取器按行读取: 输出结果: 在写这句 if err.Error() != "EOF" 时,