博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Golang之Gin框架源码解读——第四章
阅读量:3898 次
发布时间:2019-05-23

本文共 3873 字,大约阅读时间需要 12 分钟。

Gin是使用Go语言编写的高性能的web服务框架,根据官方的测试,性能是httprouter的40倍左右。要使用好这套框架呢,首先我们就得对这个框架的基本结构有所了解,所以我将从以下几个方面来对Gin的源码进行解读。

  • :Gin是如何储存和映射URL路径到相应的处理函数的
  • :Gin中间件的设计思想及其实现
  • :Gin是如何解析客户端发送请求中的参数的
  • :Gin是如何将各类格式(JSON/XML/YAML等)数据解析返回的

Gin是如何将各类格式(JSON/XML/YAML等)数据解析返回的

在看完前面三章之后,我们大致了解了Gin是如何工作、如果接收客户端请求的,但是对于一个Web框架还有一个最重要的特性的就是处理完请求后返回相应的数据。围绕着这一点,我们来看下Gin是如何解析各类数据结构的。

老规矩,我们还是以官方的示例代码来逐步分析:

func main() {
router := gin.Default() router.POST("/something", func(c *gin.Context) {
c.JSON(200, gin.H{
"status": "posted", "message": "message", "nick": "nick", }) c.XML(200,gin.H{
"status": "posted", "nick": "nick", }) c.String(http.StatusOK, "hello world") }) if err := router.Run();err != nil {
log.Println("something error"); }}

上面这个示例中我们返回了三种常见格式的数据JSON/XML/String,进入这三个方法我们可以看到:

func (c *Context) JSON(code int, obj interface{
}) {
c.Render(code, render.JSON{
Data: obj})}func (c *Context) XML(code int, obj interface{
}) {
c.Render(code, render.XML{
Data: obj})}func (c *Context) String(code int, format string, values ...interface{
}) {
c.Render(code, render.String{
Format: format, Data: values})}

这三个方法,都是调用了ContextRender方法,那么我们继续追踪:

func (c *Context) Render(code int, r render.Render) {
c.Status(code) if !bodyAllowedForStatus(code) {
r.WriteContentType(c.Writer) c.Writer.WriteHeaderNow() return } if err := r.Render(c.Writer); err != nil {
panic(err) }}func (c *Context) Status(code int) {
c.Writer.WriteHeader(code)}

可以看到这个方法就是一个标准的代理模式,Render负责传入代理对象,COntext负责执行代理对象的render.Render接口方法,来向c.Writer写出数据。我们先来看一下render.Render接口的原型:

type Render interface {
//负责写出用户指定的数据 Render(http.ResponseWriter) error //负责向头部写出ContentType的值 WriteContentType(w http.ResponseWriter)}

我们以JSON为例,来看一下该数据类型的实现方法是怎样的:

func (r JSON) Render(w http.ResponseWriter) (err error) {
if err = WriteJSON(w, r.Data); err != nil {
panic(err) } return}//这个就是JSON格式的ContentTypevar jsonContentType = []string{
"application/json; charset=utf-8"}var jsonpContentType = []string{
"application/javascript; charset=utf-8"}var jsonAsciiContentType = []string{
"application/json"}func WriteJSON(w http.ResponseWriter, obj interface{
}) error {
writeContentType(w, jsonContentType) //这里调用的是GO SDK中的序列化函数获取的字节数组 jsonBytes, err := json.Marshal(obj) if err != nil {
return err } _, err = w.Write(jsonBytes) return err}//这个函数就是将指定的ContentType,设置到响应的头部func writeContentType(w http.ResponseWriter, value []string) {
header := w.Header() if val := header["Content-Type"]; len(val) == 0 {
header["Content-Type"] = value }}//注意这个函数和调用那个函数的首字母大小写func (r JSON) WriteContentType(w http.ResponseWriter) {
writeContentType(w, jsonContentType)}

整个过程很简单,没有什么需要多说的,总体概况就两点:写出字节流写出头部信息

Gin框架支持的数据格式

要想查看Gin支持哪些数据格式,只需要哪些数据格式实现了Render接口,不过Gin官方已经在Render包中为我们罗列出来了:

var (	_ Render     = JSON{
} _ Render = IndentedJSON{
} _ Render = SecureJSON{
} _ Render = JsonpJSON{
} _ Render = XML{
} _ Render = String{
} _ Render = Redirect{
} _ Render = Data{
} _ Render = HTML{
} _ HTMLRender = HTMLDebug{
} _ HTMLRender = HTMLProduction{
} _ Render = YAML{
} _ Render = Reader{
} _ Render = AsciiJSON{
} _ Render = ProtoBuf{
})

使用方法也很明了:

router.POST("/upload", func(c *gin.Context) {
//假如我要返回json数据调用JSON方法即可 c.JSON(200, gin.H{
"status": "posted", "message": "message", "nick": "nick", }) //假如我要返回XML数据调用XML方法即可 c.XML(200,gin.H{
"status": "posted", "nick": "nick", }) //其他类似})

除了上面的常用数据格式之外,还有就是返回文件流,这个调用的是c.File("filepath"),这个方法的原型是这样的:

// 这个功能是由http包提供的func (c *Context) File(filepath string) {
http.ServeFile(c.Writer, c.Request, filepath)}

不仅是c.File()方法,而且静态文件路由router.Static("/assets", "./assets")也是最终调用的http.ServeFile,这个方法就不剖析了,涵盖点有点多,这个方法的大致作用就是根据文件的信息,设置了响应头部信息,然后再将文件输出到响应流中

转载地址:http://pqfen.baihongyu.com/

你可能感兴趣的文章
[已解决]AutoCompleteTextView 不显示匹配的内容,因为将空的内容添加进去了
查看>>
object c的浅拷贝(地址拷贝)和深拷贝(对象拷贝)
查看>>
object c son字符串的解析
查看>>
object c 非常强大的类的属性复制kcv键值码赋值
查看>>
Java中普通代码块,构造代码块,静态代码块区别及代码示例
查看>>
iOS 第4课 UILabel
查看>>
[已解决]junit.framework.AssertionFailedError: No tests found in
查看>>
“服务器端跳转”和“客户端跳转”的区别
查看>>
Datatables基本初始化——jQuery表格插件
查看>>
Servlet监听器——实现在线登录人数统计小例子
查看>>
Oracle笔记——简单查询语句 Oracle入门
查看>>
基于Hibernate和Struts2的用户管理系统小案例
查看>>
打开.class文件的方法
查看>>
基于windows平台Git+GitHub+Hexo搭建个人博客(一)
查看>>
基于windows平台Git+GitHub+Hexo搭建个人博客(二)
查看>>
Windows平台下SVN安装配置及使用
查看>>
python简便的编辑工具:jupyter notebook
查看>>
使用pip安装的时候出现 ModuleNotFoundError: No module named ‘pip‘
查看>>
Selenium自动化测试(八)之上传文件
查看>>
Selenium UI自动化(Java篇)
查看>>