15158846557 在线咨询 在线咨询
15158846557 在线咨询
所在位置: 首页 > 营销资讯 > 网站运营 > Go学习笔记 试着做一个Web框架

Go学习笔记 试着做一个Web框架

时间:2023-07-05 14:48:01 | 来源:网站运营

时间:2023-07-05 14:48:01 来源:网站运营

Go学习笔记 试着做一个Web框架:Go语言的Web框架有非常多,在日常开发中使用的有: beego、gin、revel等。这些框架也是一部分初学者的起点,这个系列的文章将会记录一个Web框架的开发历程。

这个过程中会阅读并参考一些其他的开源框架并形成自己的代码,后续的文章大概也是这个节奏,不断完善框架。

完整代码:

最简单的HTTP Server

先从最简单最原始的开始入手,在Go语言中需要一点简单的代码就可以生成一个Server,如下:

package mainimport ( "net/http")func main() { http.HandleFunc("/ping", pingHandlerFunc) http.ListenAndServe(":9527", nil)}func pingHandlerFunc(w http.ResponseWriter, r *http.Request) { w.Write([]byte("pong"))}这里发现有三个点,一个是main函数中的http.HandleFunc方法,另一个是http.ListenAndServe,最后是pingHandlerFunc

其中handler func是Router功能的一部分,从中我们可以设计出大致的样子。下文会详细描述这些组件。

Router

Router是实现路由选择、路由解析等功能。当请求到达时正确地路由至指定的handher。

如果你看过gin或者beego中的Router实现,它们通常采用树的数据结构存储。

例如echo框架中的Router(router.go)就有明显的特征:

type ( // Router is the registry of all registered routes for an `Echo` instance for // request matching and URL path parameter parsing. Router struct { tree *node routes map[string]*Route echo *Echo } node struct { //省略了node的内容 } kind uint8 children []*node methodHandler struct { //这里是存放不同method的handler func的,省略一些内容 get HandlerFunc })因为一开始并不想搞得太复杂,这里暂时使用slice来保存。

type Router struct { // 路由表 Handlers []*RouterMapping}pattern与handler func存在着映射关系(路由表),这里可以用map的数据结构存储,在这里使用一个struct来作为Entity来保存映射的关系。

type RouterMapping struct { Pattern string HandlerFunc RequestHandler}Handler Func

go中handler func比较简单,我们需要再“裹上一层”(Context),这样就可以从Writer和Request中扩展更多功能。

这个设计在一些Web Framework中也是常见操作,这里放一些源码的链接:

  1. echo - context.go
  2. gin - context.go
  3. beego - context.go
这是放出gin中Context片段

// Context is the most important part of gin. It allows us to pass variables between middleware,// manage the flow, validate the JSON of a request and render a JSON response for example.type Context struct { Request *http.Request Writer ResponseWriter}Context的生存周期通常贯穿整个请求-响应的过程。

如法炮制,将Writer和Request放在一个struct (即Context)中。

type Context struct { Writer http.ResponseWriter Request *http.Request}定义一个type,这是用户需要实现的Handler Func

type RequestHandler func(context *Context)到目前,我们已经将go的Handler Func包装完成。

Engine

engine是Web框架的入口。使用一个struct来保存类似:全局配置、一些子组件的入口,例如:Router、Render等。

在gin中,Engine的源码(gin.go)是这样的(省略了部分代码):

type Engine struct { delims render.Delims HTMLRender render.HTMLRender FuncMap template.FuncMap trees methodTrees maxParams uint16}按照设计的思路,编写代码:

type Engine struct { Router *Router}添加RunAndListen方法,这里需要将之Router中的路由表项(Handlers)进行注册。

func (e *Engine) RunAndListen(addr string) { for _, handler := range e.Router.Handlers { http.HandleFunc(handler.Pattern, func(writer http.ResponseWriter, request *http.Request) { handler.HandlerFunc(&Context{ Writer: writer, Request: request, }) }) } log.Fatal(http.ListenAndServe(addr, nil))}测试一下:

func TestRunAndListen() { e := NewEngine() e.Router.AddHandler("/ping", func(context *Context) { data := map[string]interface{}{ "say":"pong", } rawData,err := json.Marshal(data) if err != nil { panic(err) } context.Writer.Header().Set("Content-Type","application/json") context.Writer.Write(rawData) }) e.RunAndListen(":8090")}访问 http://localhost:8090/ping就能看到

{ "say": "pong"}

关键词:学习,笔记

74
73
25
news

版权所有© 亿企邦 1997-2025 保留一切法律许可权利。

为了最佳展示效果,本站不支持IE9及以下版本的浏览器,建议您使用谷歌Chrome浏览器。 点击下载Chrome浏览器
关闭