Mygin实现上下文
本篇是Mygin的第三篇
目的
- 将路由独立出来,方便后续扩展修改
- 上下文Context,对http.ResponseWriter和http.Request进行封装,实现对JSON、HTML等的支持
路由
新建一个router文件,将 Mygin实现简单的路由 中将路由部分复制出来
- 新建Mygin/router.go
package mygin
import (
"log"
"net/http"
)
// 路由节点
type methodTree struct {
method string
paths map[string]func(c *Context)
}
type methodTrees map[string]methodTree
type Router struct {
trees methodTrees
}
// 获取路由root根
func (r *Router) getRoot(method string) methodTree {
if root, ok := r.trees[method]; ok {
return root
}
r.trees[method] = methodTree{method: method, paths: make(map[string]func(c *Context))}
return r.trees[method]
}
// 添加路由方法
func (r *Router) addRoute(method, path string, ctx func(c *Context)) {
root := r.getRoot(method)
if _, ok := root.paths[path]; ok {
log.Default().Println(path, "is exist")
return
}
root.method = method
root.paths[path] = ctx
}
// Get Get方法
func (r *Router) Get(path string, handler func(c *Context)) {
r.addRoute(http.MethodGet, path, handler)
}
// Post Post方法
func (e *Engine) Post(path string, handler func(c *Context)) {
e.addRoute(http.MethodPost, path, handler)
}
- 修改Mygin/engine.go文件
package mygin
import (
"net/http"
)
type Engine struct {
Router
}
func (e *Engine) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if tree, ok := e.trees[r.Method]; ok {
if handler, ok := tree.paths[r.URL.Path]; ok {
handler(w, r)
return
}
}
w.Write([]byte("404 Not found!\n"))
}
// Default returns an Engine
func Default() *Engine {
return &Engine{
Router{
trees: make(methodTrees, 2),
}}
}
// Run 启动方法start a http server
func (e *Engine) Run(addr string) {
err := http.ListenAndServe(addr, e)
if err != nil {
return
}
}
- 相当于engine继承router,engine可以调用router中的方法。
上下文
对于1个请求来说,无法就是接收http.Request的数据处理,然后将处理后的数据http.ResponseWriter返回。虽然响应的消息体(Body)不一样,但对于同一种类型比如JSON类型,消息头(Header)和消息体(Body),而 Header 包含了状态码(StatusCode),消息类型(ContentType)等几乎每次请求都需要重新写,所以进行封装,对于后续扩展和修改都非常必要。
- 新建mygin/context.go文件
package mygin
import (
"encoding/json"
"net/http"
)
type Context struct {
Request *http.Request
Writer http.ResponseWriter
}
func writeContentType(w http.ResponseWriter, value []string) {
header := w.Header()
if val := header["Content-Type"]; len(val) == 0 {
header["Content-Type"] = value
}
}
func (c *Context) Status(code int) {
c.Writer.WriteHeader(code)
}
func (c *Context) JSON(v interface{}) error {
writeContentType(c.Writer, []string{"application/json; charset=utf-8"})
encoder := json.NewEncoder(c.Writer)
err := encoder.Encode(v)
if err != nil {
c.Status(http.StatusInternalServerError)
}
c.Status(http.StatusOK)
return err
}
func (c *Context) Html(v string) error {
writeContentType(c.Writer, []string{"text/html; charset=utf-8"})
c.Status(http.StatusOK)
_, err := c.Writer.Write([]byte(v))
return err
}
func (c *Context) String(v string) error {
writeContentType(c.Writer, []string{"text/plain; charset=utf-8"})
c.Status(http.StatusOK)
_, err := c.Writer.Write([]byte(v))
return err
}
- 在context中实现了JSON、Html、String方法
main.go文件修改
package main
import (
"gophp/mygin"
)
func main() {
engine := mygin.Default()
engine.Get("/json", func(c *mygin.Context) {
c.JSON(map[string]interface{}{
"name": "zs",
"password": "1234",
})
})
engine.Get("/html", func(c *mygin.Context) {
c.Html("<h1>hello html!</h1>")
})
engine.Get("/string", func(c *mygin.Context) {
c.String("string...")
})
engine.Run(":9501")
}
接下来看实际效果
curl -i http://localhost:9501/json
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Date: Wed, 17 Jan 2024 05:52:28 GMT
Content-Length: 32
{"name":"zs","password":"1234"}
~ curl -i http://localhost:9501/html
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Date: Wed, 17 Jan 2024 05:52:36 GMT
Content-Length: 20
<h1>hello html!</h1>
~ curl -i http://localhost:9501/string
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Date: Wed, 17 Jan 2024 05:52:42 GMT
Content-Length: 9
string...
Mygin实现上下文的更多相关文章
- 谈谈一些有趣的CSS题目(三)-- 层叠顺序与堆栈上下文知多少
开本系列,讨论一些有趣的 CSS 题目,抛开实用性而言,一些题目为了拓宽一下解决问题的思路,此外,涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题中有你感觉 ...
- 如何一步一步用DDD设计一个电商网站(七)—— 实现售价上下文
阅读目录 前言 明确业务细节 建模 实现 结语 一.前言 上一篇我们已经确立的购买上下文和销售上下文的交互方式,传送门在此:http://www.cnblogs.com/Zachary-Fan/p/D ...
- 如何一步一步用DDD设计一个电商网站(六)—— 给购物车加点料,集成售价上下文
阅读目录 前言 如何在一个项目中实现多个上下文的业务 售价上下文与购买上下文的集成 结语 一.前言 前几篇已经实现了一个最简单的购买过程,这次开始往这个过程中增加一些东西.比如促销.会员价等,在我们的 ...
- CSS——关于z-index及层叠上下文(stacking context)
以下内容根据CSS规范翻译. z-index 'z-index'Value: auto | <integer> | inheritInitial: autoApplies to: posi ...
- EF上下文对象线程内唯一性与优化
在一次请求中,即一个线程内,若是用到EF数据上下文对象,就创建一个,这也加是很多人的代码中习惯在使用上下文对象时,习惯将对象建立在using中,也是为了尽早释放上下文对象, 但是如果有一个业务逻辑调用 ...
- 【.NET深呼吸】基于异步上下文的本地变量(AsyncLocal)
在开始吹牛之前,老周说两个故事. 第一个故事是关于最近某些别有用心的人攻击.net的事,其实我们不用管它们,只要咱们知道自己是.net爱好者就行了,咱们就是因为热爱.net才会选择它.这些人在这段时间 ...
- 【.NET深呼吸】应用上下文(AppContext)
在.net 4.6中新增了一个类,叫AppContext,这个家伙嘛,技术含量不算高,只不过是在编程的时候可以方便用用而已.应用上下文允许定义一个标识(用字符串表示),并且在应用程序运行期间可以切换状 ...
- Javascript的“上下文”(context)
一:JavaScript中的“上下文“指的是什么 百科中这样定义: 上下文是从英文context翻译过来,指的是一种环境. 在软件工程中,上下文是一种属性的有序序列,它们为驻留在环境内的对象定义环境. ...
- IDDD 实现领域驱动设计-理解限界上下文
上一篇:<IDDD 实现领域驱动设计-理解领域和子域> <实现领域驱动设计>前两章内容,基本上读完了,和<领域驱动设计>不同的是,它把很多的概念都放在前面进行讲述了 ...
- IDDD 实现领域驱动设计-上下文映射图及其相关概念
上一篇:<IDDD 实现领域驱动设计-理解限界上下文> 距离上一篇有几天时间了,<实现领域驱动设计>第三章的内容都是围绕一个词-上下文映射图,我大概断断续续看了几天,总共看了两 ...
随机推荐
- 技本功|Hive优化之建表配置参数调优(一)
简介: Hive是大数据领域常用的组件之一,主要用于大数据离线数仓的运算,关于Hive的性能调优在日常工作和面试中是经常涉及的一个点,因此掌握一些Hive调优是必不可少的一项技能.影响Hive效率的主 ...
- 初探Git:理解和使用版本控制的魔法
遥远的古代,有一位美丽的仙女叫做嫦娥.她的丈夫后羿获得了令人长生不老的鹿骨露.一天,嫦娥在好奇心的驱使下,独自偷喝了这瓶仙药. 喝下仙药的瞬间,嫦娥发现自己开始飘起,越飘越高,最后飘向了月亮.嫦娥惊慌 ...
- IPv6通过公网共享文件(Windows)
前言 之前讲了如何使用IPv6进行内网穿透,这种方案实现的穿透是免费且不限速的.那么实现穿透后,我们就可以将原本Windows自带的共享功能的范围从局域网扩大到整个公网,从而实现随时随地都能访问到共享 ...
- Springboot中,如何读取配置文件中的属性
摘要:在比较大型的项目的开发中,比较经常修改的属性我们一般都是不会在代码里面写死的,而是将其定义在配置文件中,之后如果修改的话,我们可以直接去配置文件中修改,那么在springboot的项目中,我们应 ...
- Solon2 接口开发: 了解 LoadBalance
上一文的代码 HttpUtils.http(sevName, ctx.path()) (来自 "solon.cloud.httputils" 插件的工具类),内部是通过 sevNa ...
- Mycat 学习笔记
概述 1. Mycat 是什么? Mycat 是数据库中间件,连接 Java 应用程序和数据库,它的作用如下: 读写分离 数据分片:垂直拆分(分库).水平拆分(分表).垂直+水平拆分(分库分表) 多数 ...
- 跟着老猫来搞GO,系好安全带,准备发车!
为什么想要开篇这么一个系列博客主题? 我想有很多小伙伴想要问我这个,其实主要有以下几个原因. 在粉丝面前丢脸了 之前写过几篇关于java分布式系统的一些坑,然后就有小伙伴挺崇拜的,认为老猫啥都会,甚至 ...
- Django 使用swagger自定义自动生成类
完整代码:https://gitee.com/mom925/django-system之前写的Django配置swagger(https://www.cnblogs.com/moon3496694/p ...
- 谣言粉碎机?Python验证股市操盘口诀
更多精彩内容,欢迎关注公众号:数量技术宅,也可添加技术宅个人微信号:sljsz01,与我交流. 经常炒股的朋友,应该都听说过这段操盘口诀: 早上大跌要买,早上大涨要卖 下午大涨不追,下午大跌次日买 早 ...
- 【计算机网络】身份认证Oauth2
身份认证Oauth2 https://www.bilibili.com/video/BV1FL411h7es/?spm_id_from=333.999.0.0&vd_source=d11276 ...