手把手和你一起实现一个Web框架实战——EzWeb框架(二)[Go语言笔记]Go项目实战
手把手和你一起实现一个Web框架实战——EzWeb框架(二)[Go语言笔记]Go项目实战
代码仓库:
github
gitee
中文注释,非常详尽,可以配合食用
上一篇文章我们实现了框架的雏形,基本地实现了将原来的处理方法和监听处理的实例指向我们自定义的实例。封装出了GET,POST处理方法。完成了框架雏形。
本篇文章,我们将原本的handler方法中的参数 w http.ResponseWriter, req *http.Request 封装到一个新的结构体Context中,同时替代掉原来的参数,并在该结构体提供响应的一些简单的请求数据查询功能和响应处理方法。能够让我们快速获取数据以及构造响应。

一、设计这个Context
/*
@Time : 2021/8/17 下午1:46
@Author : Mrxuexi
@File : context.go
@Software: GoLand
*/
package Ez
import (
"encoding/json"
"net/http"
)
// H 为map[string]interface{}结构体起个别名,方便用户在代码中构建JSON
type H map[string]interface{}
// Context 结构体,内部封装了 http.ResponseWriter, *http.Request
type Context struct {
Writer http.ResponseWriter
Req *http.Request
//请求的信息,包括路由和方法
Path string
Method string
//响应的状态码
StatusCode int
}
//Context构造方法
func newContext(w http.ResponseWriter, req *http.Request) *Context {
return &Context{
Writer: w,
Req: req,
Path: req.URL.Path,
Method: req.Method,
}
}
// 访问参数的处理方法PostForm和Query
// PostForm 根据key拿到请求中的表单内容
func (c Context) PostForm(key string) string {
return c.Req.FormValue(key)
}
// Query 根据key获取请求中的参数
func (c Context) Query(key string) string {
return c.Req.URL.Query().Get(key)
}
//一些服用的前值方法Status处理响应状态码 SetHeader处理响应消息头
// Status 将状态码写入context,同时将通过封装起来的http.ResponseWriter方法,将状态码写入响应头
func (c Context) Status(code int) {
c.StatusCode = code
c.Writer.WriteHeader(code)
}
// SetHeader 构造响应的消息头
func (c Context) SetHeader(key string,value string) {
c.Writer.Header().Set(key,value)
}
// String 调用我们的 SetHeader和Status 方法,构造string类型响应的状态码和消息头,然后将字符串转换成byte写入到响应头
func (c Context) String(code int,values ...interface{}) {
c.SetHeader("Content-Type","text/plain")
c.Status(code)
var str = ""
for _, value := range values {
str += value.(string)
}
c.Writer.Write([]byte(str))
}
// JSON 调用我们的 SetHeader和Status 方法,构造JSON类型响应的状态码和消息头,根据我们传入的对象来构造json数据写入
func (c Context) JSON(code int,obj interface{}) {
c.SetHeader("Content-Type","application/json")
c.Status(code)
encoder := json.NewEncoder(c.Writer)
if err := encoder.Encode(obj); err != nil {
http.Error(c.Writer, err.Error(),http.StatusInternalServerError)
}
}
// Data 同上 ,但是直接写入字节数组,不再构建消息头
func (c Context) Data(code int,data []byte) {
c.Status(code)
c.Writer.Write(data)
}
// HTML 模版渲染 同上,消息体传入的是html文件
func (c Context) HTML(code int, html string) {
c.SetHeader("Content-Type","text/html")
c.Status(code)
c.Writer.Write([]byte(html))
}
我们将这些内容全部封装到了Context中,能够让我们快速获取数据以及构造响应。
如果我们没有进行封装,构造一个Json响应是十分麻烦的:
1、构造一个消息对象
//新建obj存储信息
obj := map[string]interface{}{
"name" : "Mrxuexi",
"password" : "password",
}
2、构造相应的消息头
//构造响应的消息头
w.Header().Set("Content-Type","application/json")
3、写入响应的状态码
//w写入状态码
w.WriteHeader(http.StatusOK)
4、根据已经做好的响应writer构建一个json编码器
//根据w建立一个json编码器
encoder := json.NewEncoder(w)
5、根据obj构建响应的消息体
//将obj放入消息体,处理报错
if err := encoder.Encode(obj); err != nil {
http.Error(w, err.Error(), 500)
}
如果我们进行了封装,我们只需要这样,省去了许多繁杂的工作:
c.JSON(http.StatusOK, context.H{
"name" : "Mrxuexi",
"password" : "password",
})
二、重新调整封装入口
我们将原来的Ez.go进行重构,将原来的路由表router map 封装到router.go。
HandlerFunc传入的参数改为 *Context
type HandlerFunc func(*Context)
将原来的ServeHTTP 方法作为入口,将请求传入构造context。
在router.go中进行addRoute路由注册处理和对应的请求处理。
/*
@Time : 2021/8/16 下午4:03
@Author : Mrxuexi
@File : Ez
@Software: GoLand
*/
package Ez
import (
"net/http"
)
// HandlerFunc 是Ez框架中定义的对请求的响应处理方法,传入*Context针对http请求处理
type HandlerFunc func(*Context)
// Engine 实现了"net/http"标准库中的 Handler 接口中的ServeHTTP方法
type Engine struct {
//用于存储路由处理方法
//key是方法类型加路径,value是用户的处理方法
router *router
}
// ServeHTTP 方法的实现,用于实现处理HTTP请求
func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
//根据req和w实例一个context
c := newContext(w, req)
//传入开始执行处理
engine.router.handle(c)
}
// New 路由存储结构的构造函数
func New() *Engine {
return &Engine{router: newRouter()}
}
// addRoute 方法封装在router中,在 router map[string]HandlerFunc 中存入对应处理方法
func (engine *Engine) addRoute(method string, path string, handler HandlerFunc) {
engine.router.addRoute(method, path, handler)
}
// GET 实现的是注册GET请求的路径和对应方法,调用了addRoute,存入了route 结构体的handler中
func (engine *Engine) GET(path string, handler HandlerFunc) {
engine.addRoute("GET", path, handler)
}
// POST 同上
func (engine *Engine) POST(path string, handler HandlerFunc) {
engine.addRoute("POST", path, handler)
}
func (engine *Engine) Run(addr string) (err error) {
return http.ListenAndServe(addr, engine)
}
三、重新调整封装router,路由注册处理和请求处理
所有的路由注册处理和请求处理都从入口拿到这一层来处理。
/*
@Time : 2021/8/16 下午4:03
@Author : Mrxuexi
@File : Ez
@Software: GoLand
*/
package Ez
import (
"net/http"
)
// HandlerFunc 是Ez框架中定义的对请求的响应处理方法,传入*Context针对http请求处理
type HandlerFunc func(*Context)
// Engine 实现了"net/http"标准库中的 Handler 接口中的ServeHTTP方法
type Engine struct {
//用于存储路由处理方法
//key是方法类型加路径,value是用户的处理方法
router *router
}
// ServeHTTP 方法的实现,用于实现处理HTTP请求
func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
//根据req和w实例一个context
c := newContext(w, req)
//传入开始执行处理
engine.router.handle(c)
}
// New 路由存储结构的构造函数
func New() *Engine {
return &Engine{router: newRouter()}
}
// addRoute 方法封装在router中,在 router map[string]HandlerFunc 中存入对应处理方法
func (engine *Engine) addRoute(method string, path string, handler HandlerFunc) {
engine.router.addRoute(method, path, handler)
}
// GET 实现的是注册GET请求的路径和对应方法,调用了addRoute,存入了route 结构体的handler中
func (engine *Engine) GET(path string, handler HandlerFunc) {
engine.addRoute("GET", path, handler)
}
// POST 同上
func (engine *Engine) POST(path string, handler HandlerFunc) {
engine.addRoute("POST", path, handler)
}
func (engine *Engine) Run(addr string) (err error) {
return http.ListenAndServe(addr, engine)
}
测试:
/*
@Time : 2021/8/16 下午4:01
@Author : mrxuexi
@File : main
@Software: GoLand
*/
package main
import (
"Ez"
"net/http"
)
func main() {
r := Ez.New()
r.GET("/", func(c *Ez.Context) {
c.HTML(http.StatusOK,"<h1>This is the index</h1>")
})
r.GET("/hello", func(c *Ez.Context) {
c.String(http.StatusOK, "hello")
})
r.POST("/message", func(c *Ez.Context) {
c.JSON(http.StatusOK,Ez.H{
"name" : c.PostForm("name"),
"age" : c.PostForm("age"),
})
})
r.Run(":9090")
}
index:

GET请求hello:

POST请求hello:

成功!
接上期灵魂画手环节:

参考:
[1]: https://github.com/geektutu/7days-golang/tree/master/gee-web ""gee""
[2]: https://github.com/gin-gonic/gin ""gin""
手把手和你一起实现一个Web框架实战——EzWeb框架(二)[Go语言笔记]Go项目实战的更多相关文章
- 手把手和你一起实现一个Web框架实战——EzWeb框架(三)[Go语言笔记]Go项目实战
手把手和你一起实现一个Web框架实战--EzWeb框架(三)[Go语言笔记]Go项目实战 代码仓库: github gitee 中文注释,非常详尽,可以配合食用 本篇代码,请选择demo3 这一篇文章 ...
- 手把手和你一起实现一个Web框架实战——EzWeb框架(四)[Go语言笔记]Go项目实战
手把手和你一起实现一个Web框架实战--EzWeb框架(四)[Go语言笔记]Go项目实战 代码仓库: github gitee 中文注释,非常详尽,可以配合食用 这一篇文章主要实现路由组功能.实现路由 ...
- 手把手和你一起实现一个Web框架实战——EzWeb框架(五)[Go语言笔记]Go项目实战
手把手和你一起实现一个Web框架实战--EzWeb框架(五)[Go语言笔记]Go项目实战 代码仓库: github gitee 中文注释,非常详尽,可以配合食用 本篇代码,请选择demo5 中间件实现 ...
- Go语言笔记[实现一个Web框架实战]——EzWeb框架(一)
Go语言笔记[实现一个Web框架实战]--EzWeb框架(一) 一.Golang中的net/http标准库如何处理一个请求 func main() { http.HandleFunc("/& ...
- 用C写一个web服务器(三) Linux下用GCC进行项目编译
.container { margin-right: auto; margin-left: auto; padding-left: 15px; padding-right: 15px } .conta ...
- MVC框架入门准备(二) - 语言包类与工厂模式
语言包类: 相关配置项 LANG_FOLDER : 语言包目录名,默认为Lang LANG_AUTO : 自动识别语言,默认为true DEFAULT_LANG : 默认语言,默认为zh-cn方法 取 ...
- Python之路,Day18 - 开发一个WEB聊天来撩妹吧
Python之路,Day18 - 开发一个WEB聊天来撩妹吧 本节内容: 项目实战:开发一个WEB聊天室 功能需求: 用户可以与好友一对一聊天 可以搜索.添加某人为好友 用户可以搜索和添加群 每个 ...
- 【转载】ASP.NET MVC Web API 学习笔记---第一个Web API程序
1. Web API简单说明 近来很多大型的平台都公开了Web API.比如百度地图 Web API,做过地图相关的人都熟悉.公开服务这种方式可以使它易于与各种各样的设备和客户端平台集成功能,以及通过 ...
- ASP.NET MVC Web API 学习笔记---第一个Web API程序
http://www.cnblogs.com/qingyuan/archive/2012/10/12/2720824.html GetListAll /api/Contact GetListBySex ...
随机推荐
- CentOS-Docker搭建MinIO(单点)
下载镜像 $ docker pull minio/minio 创建相关目录 $ mkdir /home/minio/data /home/minio/config -p 运行镜像(自定义Access和 ...
- Docker:docker部署PXC-5.7.21(mysql5.7.21)集群搭建负载均衡实现双机热部署方案
单节点数据库弊端 大型互联网程序用户群体庞大,所以架构必须要特殊设计 单节点的数据库无法满足性能上的要求 单节点的数据库没有冗余设计,无法满足高可用 推荐Mysql集群部署方案 PXC (Percon ...
- SpringMVC(10)实现注解式权限验证
在项目中如何处理出现的异常,在每个可能出现异常的地方都写代码捕捉异常?这显然是不合理的,当项目越来越大是也是不可维护的.那么如何保证我们处理异常的代码精简且便于维护呢?这就是本篇要讲的内容->异 ...
- 【分布式】CAP理论及其应用
CAP Theorem CAP 指的就是 "consistency 一致性","availability 可用性" "partition-tolera ...
- NTFS安全权限
一.NTFS权限概述 1.通过设置NTFS权限,实现不同的用户访问不同的对象的权限 2.分配了真确的访问权限后,用户才能访问其资源 3.设置权限防止资源被篡改.删除 二.文件系统概述 文件系统即在外部 ...
- CPU 几核
1.设备管理器:打开"处理器",出现几个就是几核
- vs2013恢复默认设置
选择 工具->import or export settings(工具->导入导出设置),选择最下面一项即可
- MQTT 1——物联网集成项目技术选型与说明
最近做的JAVA项目与物联网设备有集成,记录一下从技术选型到实现,整合: 1.通信协议技术选型,MQTT技术介绍2.MQTT服务端安装,客户端测试3.MQTT客户端与Spring MVC整合 1.项目 ...
- 团队开发day10
项目整合成功,测试功能基本达到,目标完成!
- WinForm使用DataGridView实现类似Excel表格的查找替换
在桌面程序开发过程中我们常常使用DataGridView作为数据展示的表格,在表格中我们可能要对数据进行查找或者替换. 其实要实现这个查找替换的功能并不难,记录下实现过程,不一定是最好的方式,但它有用 ...