Go语言笔记[实现一个Web框架实战]——EzWeb框架(一)

一、Golang中的net/http标准库如何处理一个请求

  1. func main() {
  2. http.HandleFunc("/", handler)
  3. http.HandleFunc("/count", counter)
  4. log.Fatal(http.ListenAndServe("localhost:9090", nil))
  5. }
  6. func handler(w http.ResponseWriter, r *http.Request) {
  7. fmt.Fprintf(w, "URL.Path = %q\n", r.URL.Path)
  8. }

标准库中实现了监听,映射路由,和解析http报文。

浏览器的请求,http.ListenAndServe方法中,第一个参数是监听地址响,第二个参数代表处理所有的HTTP请求的实例,nil代表使用标准库中的实例处理。

我们通过第二个参数,转入到我们的实例,这样所有的HTTP请求就都交给了我们的实例来处理。

二、实现http.Handler接口

  1. /*
  2. @Time : 2021/8/5 下午4:08
  3. @Author : mrxuexi
  4. @File : main
  5. @Software: GoLand
  6. */
  7. package main
  8. import (
  9. "fmt"
  10. "log"
  11. "net/http"
  12. )
  13. type Engine struct {}
  14. /**
  15. * @Description:
  16. 对Engine结构体的ServeHttp方法实现。ServeHTTP是Handler接口中的一个方法,在这里我们对这个方法进行实现,放入到我们的Engine中。这里就用上了我们的自定义方法来处理请求。
  17. * @receiver engine
  18. * @param w http.ResponseWriter(通过该ResponseWriter构造针对该请求的响应)
  19. * @param req *http.Request(Request中包括了发送来的HTTP请求的全部信息)
  20. */
  21. func (engine *Engine)ServeHTTP(w http.ResponseWriter, req *http.Request) {
  22. switch req.URL.Path {
  23. case "/":
  24. fmt.Fprintf(w,"URL.Path = %q\n", req.URL.Path)
  25. case "/hello":
  26. for k, v := range req.Header {
  27. fmt.Fprintf(w,"Header[%q] = %q \n", k, v)
  28. }
  29. default:
  30. fmt.Fprintf(w,"404 NOT FOUND: %s\n", req.URL)
  31. }
  32. }
  33. func main() {
  34. engine := new(Engine)
  35. //此处后者的参数填入engine,让请求交由我们实现的engine实例来处理
  36. log.Fatal(http.ListenAndServe(":9090",engine))
  37. }

三、实现简单的GET,POST方法,实现框架简单原型

设计自己的Engine结构体,然后将原来启动web项目的

  1. log.Fatal(http.ListenAndServe(":9090",engine))

封装成Run(addr),并将第二个参数的默认实例,直接写为我们的engine实例。

  1. func (engine *Engine) Run(addr string) (err error) {
  2. return http.ListenAndServe(addr, engine)
  3. }

这里engine涉及到一个转换,实现了接口方法的struct转换为接口类型

我们要实现的GET,POST方法。作用是,将路由和方法,注册进来,然后在监听的时候进行查找和处理。

这里设计一个router放入到我们的Engine结构体中:

  1. // Engine 实现了"net/http"标准库中的 Handler 接口中的ServeHTTP方法
  2. type Engine struct {
  3. //用于存储路由处理方法
  4. //key是方法类型加路径,value是用户的处理方法
  5. router map[string]HandlerFunc
  6. }

我们的GET和POST方法就是这样实现的,调用addRoute方法,将路由和响应方法存入到router中:

  1. // GET 实现的是Engine的处理GET请求的方法,注册到router中
  2. func (engine *Engine) GET(path string, handler HandlerFunc) {
  3. engine.addRoute("GET", path, handler)
  4. }
  5. // POST 同上
  6. func (engine *Engine) POST(path string, handler HandlerFunc) {
  7. engine.addRoute("POST", path, handler)
  8. }

这里就是addRoute方法,method-path作为key,handler作为value

  1. // Engine 中 addRoute 方法,在 router map[string]HandlerFunc 中存入对应处理方法
  2. //存入形式为例如:{ "GET-/index" : 定义的处理方法 }engine
  3. func (engine *Engine) addRoute(method string, path string, handler HandlerFunc) {
  4. key := method + "-" + path
  5. engine.router[key] = handler
  6. }

我们再重写Handler接口中的ServeHTTP方法,通过req请求的路由查找router中注册的方法执行。

  1. // ServeHTTP 方法的实现,用于实现处理HTTP请求
  2. // 先解析req对应传入的路径,查找router中,如果有相应的处理方法,则执行处理方法,如果没有则返回找不到的提示
  3. // 来自Handler接口
  4. func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
  5. key := req.Method + "-" + req.URL.Path
  6. //根据请求req中的数据,从router中取出对应的方法
  7. if handler, ok := engine.router[key]; ok {
  8. handler(w, req)
  9. } else {
  10. fmt.Fprintf(w, "could not find the route: %s\n", req.URL)
  11. }
  12. }

雏形的全部源码:

  1. /*
  2. @Time : 2021/8/16 下午4:03
  3. @Author : Mrxuexi
  4. @File : Ez
  5. @Software: GoLand
  6. */
  7. package Ez
  8. import (
  9. "fmt"
  10. "net/http"
  11. )
  12. // HandlerFunc 是Ez框架中定义的对请求的响应处理方法,默认传入这两个参数,针对http请求处理
  13. type HandlerFunc func(http.ResponseWriter, *http.Request)
  14. // Engine 实现了"net/http"标准库中的 Handler 接口中的ServeHTTP方法
  15. type Engine struct {
  16. //用于存储路由处理方法
  17. //key是方法类型加路径,value是用户的处理方法
  18. router map[string]HandlerFunc
  19. }
  20. // ServeHTTP 方法的实现,用于实现处理HTTP请求
  21. // 先解析req对应传入的路径,查找router中,如果有相应的处理方法,则执行处理方法,如果没有则返回找不到的提示
  22. // 来自Handler接口
  23. func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
  24. key := req.Method + "-" + req.URL.Path
  25. //根据请求req中的数据,从router中取出对应的方法
  26. if handler, ok := engine.router[key]; ok {
  27. handler(w, req)
  28. } else {
  29. fmt.Fprintf(w, "could not find the route: %s\n", req.URL)
  30. }
  31. }
  32. // New 是Ez.Engine的构造函数
  33. func New() *Engine {
  34. return &Engine{router: make(map[string]HandlerFunc)}
  35. }
  36. // Engine 中 addRoute 方法,在 router map[string]HandlerFunc 中存入对应处理方法
  37. //存入形式为例如:{ "GET-/index" : 定义的处理方法 }engine
  38. func (engine *Engine) addRoute(method string, path string, handler HandlerFunc) {
  39. key := method + "-" + path
  40. engine.router[key] = handler
  41. }
  42. // GET 实现的是Engine的处理GET请求的方法,注册到router中
  43. func (engine *Engine) GET(path string, handler HandlerFunc) {
  44. engine.addRoute("GET", path, handler)
  45. }
  46. // POST 同上
  47. func (engine *Engine) POST(path string, handler HandlerFunc) {
  48. engine.addRoute("POST", path, handler)
  49. }
  50. // Run 用于启动服务,直接制定用该路由的engine
  51. func (engine *Engine) Run(addr string) (err error) {
  52. return http.ListenAndServe(addr, engine)
  53. }

尝试使用:

  1. /*
  2. @Time : 2021/8/16 下午4:01
  3. @Author : mrxuexi
  4. @File : main
  5. @Software: GoLand
  6. */
  7. package main
  8. import (
  9. "Ez"
  10. "fmt"
  11. "net/http"
  12. )
  13. func main() {
  14. r := Ez.New()
  15. r.GET("/hello", func(w http.ResponseWriter, req *http.Request) {
  16. fmt.Fprintf(w,"Hello")
  17. })
  18. r.Run(":9090")
  19. }

成功!

后续我们继续完善内容

参考:

[1]: https://github.com/geektutu/7days-golang/tree/master/gee-web ""gee""

[2]: https://github.com/gin-gonic/gin ""gin""

Go语言笔记[实现一个Web框架实战]——EzWeb框架(一)的更多相关文章

  1. 手把手和你一起实现一个Web框架实战——EzWeb框架(二)[Go语言笔记]Go项目实战

    手把手和你一起实现一个Web框架实战--EzWeb框架(二)[Go语言笔记]Go项目实战 代码仓库: github gitee 中文注释,非常详尽,可以配合食用 上一篇文章我们实现了框架的雏形,基本地 ...

  2. 手把手和你一起实现一个Web框架实战——EzWeb框架(三)[Go语言笔记]Go项目实战

    手把手和你一起实现一个Web框架实战--EzWeb框架(三)[Go语言笔记]Go项目实战 代码仓库: github gitee 中文注释,非常详尽,可以配合食用 本篇代码,请选择demo3 这一篇文章 ...

  3. 手把手和你一起实现一个Web框架实战——EzWeb框架(四)[Go语言笔记]Go项目实战

    手把手和你一起实现一个Web框架实战--EzWeb框架(四)[Go语言笔记]Go项目实战 代码仓库: github gitee 中文注释,非常详尽,可以配合食用 这一篇文章主要实现路由组功能.实现路由 ...

  4. 手把手和你一起实现一个Web框架实战——EzWeb框架(五)[Go语言笔记]Go项目实战

    手把手和你一起实现一个Web框架实战--EzWeb框架(五)[Go语言笔记]Go项目实战 代码仓库: github gitee 中文注释,非常详尽,可以配合食用 本篇代码,请选择demo5 中间件实现 ...

  5. ASP.NET MVC Web API 学习笔记---第一个Web API程序

    http://www.cnblogs.com/qingyuan/archive/2012/10/12/2720824.html GetListAll /api/Contact GetListBySex ...

  6. 【转载】ASP.NET MVC Web API 学习笔记---第一个Web API程序

    1. Web API简单说明 近来很多大型的平台都公开了Web API.比如百度地图 Web API,做过地图相关的人都熟悉.公开服务这种方式可以使它易于与各种各样的设备和客户端平台集成功能,以及通过 ...

  7. ASP.NET MVC Web API 学习笔记---第一个Web API程序【转】

    http://www.cnblogs.com/qingyuan/archive/2012/10/12/2720824.html 1. Web API简单说明 近来很多大型的平台都公开了Web API. ...

  8. ASP.NET MVC Web API 学习笔记---第一个Web API程序---近来很多大型的平台都公开了Web API

    1. Web API简单说明 近来很多大型的平台都公开了Web API.比如百度地图 Web API,做过地图相关的人都熟悉.公开服务这种方式可以使它易于与各种各样的设备和客户端平台集成功能,以及通过 ...

  9. MyBatis整合Spring+SpringMVC搭建一个web项目(SSM框架)

    本文讲解如何搭建一个SSM架构的web站点 [工具] IDEA.SqlYog.Maven [简述] 该项目由3个模块组成:dao(数据访问层).service(业务处理层).web(表现层) dao层 ...

随机推荐

  1. CentOS7 安装搭建docker环境

    一.Docker简介 Docker 版本 :版本分为:社区版CE  企业版EE 社区版分为stable和edge俩种发行方式: stable版本:是季度版发行(三月一更新) edge版本:是月度版发行 ...

  2. 探究国内CRM系统哪家公司做的最好?

    国内CRM系统哪家公司做的最好?相信这是很多人关心的话题.但这是一个伪命题,因为无论什么产品,都没有一个确定的结论来证明哪个产品最好.我们只能根据它的功能.适用性.价格等来判断哪个最合适.所以小编只能 ...

  3. CRM企业管理系统一年多少钱?

    CRM系统一年多少钱?这是很多企业管理者比较关心的问题.目前市面上的CRM系统分为本地部署型和云部署型.云部署型CRM费用相对较低,只需要按需购买账号,连接网络即可使用:本地部署型CRM费用较高,企业 ...

  4. Hibernate框架(五)面向对象查询语言和锁

    Hibernate做了数据库中表和我们实体类的映射,使我们不必再编写sql语言了.但是有时候查询的特殊性,还是需要我们手动来写查询语句呢,Hibernate框架为了解决这个问题给我们提供了HQL(Hi ...

  5. XCTF_MFC逆向

    讲道理这题有点脑洞,也可能我太菜了,首先对mfc就不太熟悉,不知道是个啥玩意,只能边看大佬的wp百度边做了,之后要恶补一下mfc的知识了. 题目一开始说flag在控件中,看到大佬都是用Mfcspy来找 ...

  6. Acunetix在SDLC中的安全性测试

    DevOps只是害怕尝试新事物.它们用于Selenium测试,这些测试占用了管道并提供了难以解释的结果,但是与此同时,它们经常避开了DAST测试,这远没有那么麻烦. 由于他们的应用程序是完全用Java ...

  7. flask 的安装与使用

    一.Flask Flask 是一个轻量级的框架,可以将数据库中的数据呈现到页面上(动态网站). 之前搭建的网站是静态网站(没有连接数据库)页面的数据不会改变.但是现在用的网站都是动态网站. 1.下载F ...

  8. layim即时通讯实例各功能整合

    一.系统演示1.1 聊天窗体主界面演示 1.2 模拟两人在线聊天(点击图片查看演示视频) 1.3 在线演示> 在线演示,点击进入系统到这里,若是您想要的,接下来听我娓娓道来二.开发工具开发软件: ...

  9. C语言:伪代码

    伪代码(Pseudocode)是一种算法描述语言.使用伪代码的目的是为了使被描述的算法可以容易地以任何一种编程语言(C, Java, Pascal)实现.因此,伪代码必须结构清晰,代码简单,可读性好, ...

  10. 家庭账本开发day03

    今天在编写form表单提交时遇到很多问题,在向servlet提交请求时找不到资源, 在网上查找学习了相关的信息,找到原因,添加注解或者配置xml文件的相关映射 解决问题.成功完成了账单添加的功能.