Gin封装的最好的地方就是context和对response的处理. github的README的介绍,基本就是对这两个东西的解释. 本篇文章主要解释context的使用方法, 以及其设计原理

为什么要将Request的处理封装到Context中

在阅读gin的源码时, 请求的处理是使用type HandlerFunc func(*Context)来处理的. 也就是

func(context *gin.Context) {
context.String(http.StatusOK, "some post")
}

参数是gin.Context, 但是查看源码发现其实gin.Context在整个框架处理的地方只有下面这段:

func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
c := engine.pool.Get().(*Context)
c.writermem.reset(w)
c.Request = req
c.reset() engine.handleHTTPRequest(c) engine.pool.Put(c)
}

那为什么还要利用Context来处理呢. gin的context实现了的context.Context Interface.

经过查看context.Context相关资料, Context的最佳运用场景就是对Http的处理. 封装成Conetxt另外的好处就是WithCancel, WithDeadline, WithTimeout, WithValue这些context包衍生的子Context就可以直接来使用.

gin.Context设计

这个模块比较简单, 就是从gin.Context中Set Key-Value, 以及各种个样的Get方法, 如GetBool, GetString等

实现这些功能也很简单, 其实就是一个map

// Keys is a key/value pair exclusively for the context of each request.
Keys map[string]interface{}

Input Data

这个模块相当重要了, gin的README基本上都在介绍这个模块的用法.

Param (我自己的叫法: 路由变量)

gin的标准叫法是Parameters in path. restful风格api如/user/john, 这个路由在gin里面是/user/:name, 要获取john就需要使用Param函数

name := context.Param("name")

这个方法实现也很简单, 就是在tree.go里面根据路由相关规则解析出来然后赋值给gin.Context的Params.

Query

/welcome?firstname=Jane&lastname=Doe这样一个路由, first, last即是Querystring parameters, 要获取他们就需要使用Query相关函数.

c.Query("first") // Jane
c.Query("last") // Doe

当然还有其他相关函数:

QueryMap

DefaultQuery 这个默认值的实现更加简单, 当QueryString中不包含这个值, 直接返回填入的值

这些方法是的实现是利用net/http的Request的方法实现的

PostForm

FormFile

对于文件相关的操作, 一般生产情况下不建议这样使用, 因为把文件上传到服务器磁盘, 还得磁盘相关的监控. 我觉得最好利用云服务商相关的对象存储, 如:阿里云OSS, 七牛云对象存储, AWS的对象存储等来做文件的相关操作

Bind

内置的有json, xml, protobuf, form, query, yaml. 这些Bind极大的减少我们自己去解析各种个样的数据格式, 提高我们的开发速度

Bind的实现都在gin/binding里面. 这些内置的Bind都实现了Binding接口, 主要是Bind()函数.

context.BindJSON() 支持MIME为application/json的解析

context.BindXML() 支持MIME为application/xml的解析

context.BindYAML() 支持MIME为application/x-yaml的解析

context.BindQuery() 只支持QueryString的解析, 和Query()函数一样

context.BindUri() 只支持路由变量的解析

Context.Bind() 支持所有的类型的解析, 这个函数尽量还是少用(当QueryString, PostForm, 路由变量在一块同时使用时会产生意想不到的效果), 目前测试Bind不支持路由变量的解析, Bind()函数的解析比较复杂, 这部分代码后面再看

Response

对Header的支持

  • Header
  • GetHeader

    这里的Header是写到Response里面的Header. 对于客户端发的请求的Header可以通过context.Request.Header.Get("Content-Type")获取
context.Header("jwt", "123456")  // 写到Response的Header
clientIp := context.GetHeader("X-Forwarded-For") // 从Request中获取Header
fmt.Println(clientIp)

Cookie

提供对session, cookie的支持

[cookie和session](https://www.cnblogs.com/mayanan/p/15672208.html)

render

做api常用到的其实就是gin封装的各种render. 目前支持的有:

func (c *Context) JSON(code int, obj interface{})

func (c *Context) Protobuf(code int, obj interface{})

func (c *Context) YAML(code int, obj interface{}) ...

当然我们可以自定义渲染, 只要实现func (c *Context) Render(code int, r render.Render)即可.

这里我们常用的是一个方法是: gin.H{"error": 111}. 这个结构相当实用, 各种render都支持. 其实这个结构很简单就是type H map[string]interface{}, 当我们要从map转换各种各样结构时, 不妨参考gin这里的代码

Context说到这里基本就说完了, 这里介绍的方法都是开发中特别实用的方法. context的代码实现也特别有条理, 建议可以看看这部分代码

gin源码解读3-gin牛逼的context的更多相关文章

  1. gin源码解读1-net/http的大概流程

    gin框架预览 router.Run()的源码: func (engine *Engine) Run(addr ...string) (err error) { defer func() { debu ...

  2. gin 源码阅读(1) - gin 与 net/http 的关系

    gin 是目前 Go 里面使用最广泛的框架之一了,弄清楚 gin 框架的原理,有助于我们更好的使用 gin. 这个系列 gin 源码阅读会逐步讲明白 gin 的原理. gin 概览 想弄清楚 gin, ...

  3. gin源码解读2-揭开gin的神秘面纱

    数据如何在gin中流转 func main() { gin.SetMode(gin.DebugMode) // 设置为开发模式 router := gin.Default() _ = router.S ...

  4. gin 源码阅读(2) - http请求是如何流入gin的?

    推荐阅读: gin 源码阅读(1) - gin 与 net/http 的关系 本篇文章是 gin 源码分析系列的第二篇,这篇文章我们主要弄清一个问题:一个请求通过 net/http 的 socket ...

  5. gin 源码阅读(5) - 灵活的返回值处理

    gin 源码阅读系列文章列表: gin 源码阅读(1) - gin 与 net/http 的关系 gin 源码阅读(2) - http请求是如何流入gin的? gin 源码阅读(3) - gin 路由 ...

  6. gin源码剖析

    介绍 Gin 是一个 Golang 写的 web 框架,具有高性能的优点,基于 httprouter,它提供了类似martini但更好性能(路由性能约快40倍)的API服务.官方地址:https:// ...

  7. Alamofire源码解读系列(二)之错误处理(AFError)

    本篇主要讲解Alamofire中错误的处理机制 前言 在开发中,往往最容易被忽略的内容就是对错误的处理.有经验的开发者,能够对自己写的每行代码负责,而且非常清楚自己写的代码在什么时候会出现异常,这样就 ...

  8. 源码解读·RT-Thread操作系统从开机到关机

    本篇内容比较简单,但却很繁琐,篇幅也很长,毕竟是囊括了整个操作系统的生命周期.这篇文章的目的是作为后续设计多任务开发的铺垫,后续会单独再抽出一篇分析任务的相关知识.另外本篇文章以单核MCU为背景,并且 ...

  9. HashTable、HashMap与ConCurrentHashMap源码解读

    HashMap 的数据结构 ​ hashMap 初始的数据结构如下图所示,内部维护一个数组,然后数组上维护一个单链表,有个形象的比喻就是想挂钩一样,数组脚标一样的,一个一个的节点往下挂. ​ 我们可以 ...

随机推荐

  1. 解决Tomcat9打印台乱码问题

    问题描述: Tomcat打印台.打印出来的字体全是乱码后的显示.影响视觉体验,不利于bug查找和错误排查.故寻找方法去修改. 解决方法: 1.找到目录 2.对日志参数进行修改 3.改动编码 4.修改成 ...

  2. 【LeetCode】1461. 检查一个字符串是否包含所有长度为 K 的二进制子串 Check If a String Contains All Binary Codes of Size K

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 统计长度为 K 的子串个数 日期 题目地址:https ...

  3. 【LeetCode】490. The Maze 解题报告 (C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 BFS 日期 题目地址:https://leetcod ...

  4. 【LeetCode】122.Best Time to Buy and Sell Stock II 解题报告(Java & Python & C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 日期 题目地址:https://leetcode.c ...

  5. 【LeetCode】779. K-th Symbol in Grammar 解题报告(Python)

    [LeetCode]779. K-th Symbol in Grammar 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingz ...

  6. 1083 - Histogram

    1083 - Histogram   PDF (English) Statistics Forum Time Limit: 2 second(s) Memory Limit: 64 MB A hist ...

  7. 第47篇-解释执行的Java方法调用native方法小实例

    举个小实例,如下: public class TestJNI { static { // 程序在加载时,自动加载libdiaoyong.so库 System.loadLibrary("dia ...

  8. Redis -使用 Bitmap

    redis数据类型 String.Set.Zset.List.hash       Bitmap . 四种统计类型: 二值状态统计: 聚合统计: 排序统计: 基数统计 二值状态统计: 就是集合中的元素 ...

  9. Chapter 7 Confounding

    目录 7.1 The structure of confounding Confounding and exchangeability Confounding and the backdoor cri ...

  10. 使用JavaScript 中的Math对象和勾股定理公式,计算鼠标的位置与页面图片中心点的距离,根据距离对页面上的图片进行放大或缩小处理。距离远时图片放大,距离近时图片缩小

    查看本章节 查看作业目录 需求说明: 使用JavaScript 中的Math对象和勾股定理公式,计算鼠标的位置与页面图片中心点的距离,根据距离对页面上的图片进行放大或缩小处理.距离远时图片放大,距离近 ...