用 Go 来实现 Koa 的洋葱模型《Koa for Go》🧅
1. 简述
⚜️ 本项目是更好这两天接触到 GO 突发奇想的想要实现一个
GO 版的 Koa 玩玩, 这里就只是实现了 Koa 的核心思想
洋葱模型以及简单的路由中间件,其他没有继续深入的继续进行了。
👉 仓库地址:Koa for go 欢迎 Star
2. 项目结构
先来看一下项目的目录树结构和功能划分
KoaForGo
├── README.md
├── main.go // 入口,实现了使用例子
├── koa // 核心实现 core
│ ├── application.go // koa 入口 主要用于开启 Http 链接,设置中间件
│ ├── compose.go // 用于组装中间件
│ └── context.go // context 没啥好说的,简单的上下文
└── router // 路由中间件
├── method // 请求方式目录
│ └── method.go // 常量方式存储 Http 请求方式 GET,POST,PUT,DELETE
└── router.go // 路由中间件实现
3. 具体实现
事实上 Go 是一门强类型语言,所以我一开始直接参考(照搬) Koa.js 的方式
来到 Go 这里尝试的时候发现根本行不通。我也就这两天才接触到 Go 语言了解到 Go 的写法
所以一开始到处碰壁写出一堆报错的代码可难受了。
3.1 Koa.js 洋葱模型实现
我先把 Koa.js 的代码贴上来我们来分析一下 Koa.js 实现的主要方式
从上面代码可以看的出来,Koa.js 中主要实现洋葱模型的方式其实挺简单的。
首先是一进来就是一通判断,参数是不是数组,数组里面的元素是不是都是 function,
不过这些对于我们现在要研究的东西并不重要,接下来的才是重点。
在 compose 这个 function 中返回了一个函数提供外部调用,这是开启运行中间件的入口。
compose 中返回的 function 还存在一个 dispatch 的函数,这个函数是实现洋葱模型执行的核心 function,
dispatch function 会递归的被调用,每次调用都会从 middleware 中获取一个中间件进行调用,
并递归返回将下一个中间件作为当前中间件的 next 参数传入。
3.2 Go 实现洋葱模型的具体办法
来到 Go 这边,我一开始用照搬的方式,写是写出来了就是运行起来一点都不洋葱 🧅,
按照洋葱模型按照中间件的执行顺序应该是 1 -> 2 -> 3 -> 2 -> 1 这种。
然鹅 🦢 我实现出来的执行出来的是 3 -> 2 -> 1 emmmm ~ ~ 这就难受了,暂时没搞明白是为嘛,
大概是因为 js 和 Go 的执行机制不大一样把。
然后我换了很多方式最后使用了链表的方式实现了洋葱模型,废话说了很多了,好!上代码。
– ./koa/compose.go
具体的看注释,核心就是链表模式实现,哦对了看看 MiddlewareType 这个结构体
– ./koa/application.go row:30
反正就是一个最简单的链表结构。接下来看看 context。
– ./koa/context.go
Context 的话因为时间问题没有进行太多的封装,就只是简单的组合了一些东西形成了 Context 结构体。
主要给 Context 实现了一个 Next 的一个方法,
主要就是实现了执行下一个中间件的操作,然后将中间件链表载入下一个,然后等待下一个调用,
如果下一个中间件为空那就不操作。
差不多就是上面的几个组件支撑了我这个 Koa for Go 的洋葱模型的实现了。
因为接触 Go 的时间太短了,没进行深入的学习了解 Go 的其他骚操作只能按照自己能想象到的方式实现了出来,
广大哥哥评论区指点迷津,非常感谢。
3.3 入口方法
好的,贴图为先 ~
– ./koa/application.go
主要的一些东西都在注释上写了,直接看注释吧。总觉得 application.go 这里一个 Use 和
compose.go 中的一个 Use 呃 ~ 怪怪的不过我起名困难那就先这样子吧,知道就好了,将就。
3.4 Router 路由中间件
这个的话其实就是简单的实现了一下路由的分发而已,感兴趣的可以自己去看看源码,应该不难。
如果有需要我在解释一下的话,那就评论区留言吧,要是需要我在另外写一下介绍一下。
4. 使用方式
说完源码,现在来说说怎么用吧。用法我个人感觉其实跟 Koa.js 也差不多。
4.1 简单应用
先实例化一个 Koa 然后写自己的中间件实现,中间件会接收一个 Context
里面有 Next 方法可以调用下一个中间件
最后监听一下端口,就正式启动了一个 http 服务了,还是实现了这个洋葱模型的,
这里的话我写了三个中间件
第一个,按照已知洋葱模型的 1 -> 2 -> 3 -> 2 -> 1
的原因知道第一个中间件在调用 Next 之后的代码将在最后被调用,所以说,我就在第一个中间件后面
调用 Response.Write 把 Body 的数据返回去。
第二个,就是简单的设置了一下 Body 的数据
第三个,因为 Body 是结构体,通常来说我们都是要返回的是一个 json 结构的数据给前端,
所以这里就把结构体进行了转换并且赋值到了 JsonBody 中方便第一个中间件返回数据。
func main() {
app := koa.Koa{}
// 将数据写入到返回
app.Use(koa.MiddlewareType{ Action: func(context *koa.Context) {
context.Next()
context.Response.Write(context.JsonBody)
}})
// 往 body 中装入返回信息
app.Use(koa.MiddlewareType{ Action: func(context *koa.Context) {
context.Body = VO{ Message: "hello koa for go!" }
context.Next()
}})
// 将 返回的对象转为 json 对象
app.Use(koa.MiddlewareType{ Action: func(context *koa.Context) {
context.JsonBody, _ = json.Marshal(context.Body)
}})
app.Listen(5000) // 监听 5000 端口
}
这就是一个简单的应用例子。现在去浏览器打开一下 localhost:5000/
就可以成功的请求并返回了消息
{
"Message": "hello koa for go!"
}
4.2 使用 Router
上面简单的使用上了,但是还有一个问题就是没办法让不同的路由匹配到不同的函数中去。这个时候就要用上路由了。
下面是一个使用路由的栗子 🌰
跟比上面的那个 🌰 多了一点的就是多实例化了一个路由的结构体,这个结构体里面实现了常用的
GET, POST, Put, DELETE 这几个常用的请求方式提供调用,在这里我分别给 /home 这个路由把这几种请求
都实现了,然后返回的消息都不一样。
在最后调用 router.ToMiddleware 函数将会返回一个 koa of go 的中间,只要把这个挂载到 app
中这个路由就应用上了,现在用不同的请求去请求 /home 这个 uri 都会返回不同的结果出来了。
func main() {
app := koa.Koa{}
router := router.Router{}
router.Get("/home", func(context *koa.Context) {
context.Body = success(MessageData{ Info: "hello this is home Get"})
})
router.Post("/home", func(context *koa.Context) {
context.Body = success(MessageData{ Info: "hello this is home Post"})
})
router.Put("/home", func(context *koa.Context) {
context.Body = success(MessageData{ Info: "hello this is home Put"})
})
router.Delete("/home", func(context *koa.Context) {
context.Body = success(MessageData{ Info: "hello this is home Delete"})
})
// 将数据写入到响应
app.Use(koa.MiddlewareType{ Action: func(context *koa.Context) {
context.Next()
context.JsonBody, _ = json.Marshal(context.Body)
context.Response.Write(context.JsonBody)
}})
// 装载路由
app.Use(router.ToMiddleware())
app.Listen(5000)
}
5. 结束语
好的以上就是这次我要介绍的 Koa fo Go 的全部内容了,作为一个正经的 node 程序员我现在的主业是 C#
现在对于 Go 其实也没太多的深入,所以哪里有问题的还请大家多多指教。
经过这次写这个 Koa for Go 我感觉我貌似又可以搞 Go 了,不过我觉得这只是我的错觉而已。
感谢您的观看 ~~ 谢谢!
你的点赞是我更新的动力,我将不定期为的搞事情为大家带来有趣好玩的东西~
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: