1. AsciiJSON
- 使用 AsciiJSON 生成具有转义的非 ASCII 字符的 ASCII-only JSON:
- 把map里的字符串转成Ascii码放到JSON里然后输出
2. HTML渲染
- 使用方法 loadHTMLGlob()、loadHTMLFiles()
- loadHTMLGlob可以加载嵌套的文件夹
- 可以自定会议分隔符和模板功能
- 遇到的奇怪问题:time.Date()报错
3. HTTP2 Server 推送
- 【存在的问题】:
- HTTP2 push 是为了解决HTTP1的时候存在的一个问题——所有资源的请求都是一问一答,导致网络在很多时候都是在等待中空闲着。
- 【HTTP2是如何解决的】:
- 在浏览器第一次向服务器请求一个页面之后,服务器不光会把被请求的页面发回去,还会发送一个 push_promise,push_promise描述了服务器认为浏览器将要使用的请求。然后服务器会把push_promise描述的请求结果返回给浏览器(虽然这时浏览器并没有请求这个资源)。当一开始浏览器接收到push_promise的时候,若他发现自己确实需要使用这个请求,那么她就不会再发送请求了,而是等待服务器的发送。
- 服务器:【虽然你没说,但我猜你要用,我现在就给你发过去,你想要的时候就不用再跑来告诉我了。你要是真用得上就收着,用不上就扔了吧】
4. JSONP
- 用于解决的问题:浏览器的跨域请求资源问题
- 解决方法:调用目标服务器提供的js文件,传过去的参数中有自己本地的回调函数的名字(比如 handler)和一些参数,这样就会收到一个用回调函数名字包裹的数据(如 handler({“time”: “2019-08-22”})),这样就实现了跨域请求资源(请求到了 time)。
5. Multipart/Urlencoded 绑定
- 可以将结构体与传入的表单数据进行自动绑定
- 显式声明 : shouldBindWith() ; 或自动绑定 ShouldBind()
- 可以实现十分方便的处理前端传来的表单数据!
6. Multipart/Urlencoded 表单
- 个人理解是 PostForm这个方法可以从传过来的表单中读取某个数据
而 DefaultPostForm方法则可以在对应数据没有值的时候,赋一个默认值给他
7. PureJSON
- 可以避免JSON把特殊HTML字符转换成Unicode
8. Query 和 post form
- Query和PostForm的基本用法
9. SecureJSON
- 防止json劫持,会在返回的json前面加上前缀(如 while(1) )
- 也可以自定义SecureJSON的前缀
10. 单文件上传
- c.FormFile(“file”) 传入的参数是对应着 curl中传入文件的参数
- curl 文件路径前记得加上 @
- 可以设置内存限制
11. 多文件上传
- 从context中获得传入的多表单数据存入form
- 从form中取得传入的多个文件的集合
- 虽然官方文档中这个参数写的是“upload[ ]”,但实际上只是个名字而已,去掉[ ]也可以
12. 不使用默认的中间件
- 若使用 r := gin.Default() 来初始化,则会默认使用 Logger 和 Recovery 中间件
- 使用r := gin.New() 则不会加载默认的中间件了
13. 从Reader读取数据
- c.DataFromReader(状态码,返回内容长度,返回内容类型,reader,额外头文件)
- 返回了reader中的数据,这个reader是实现了reader接口的对象,可以来自很多地方比如读取网页、文件、字符串等等
【golang IO 部分有待深入学习】
14. 优雅的重启或关机
什么叫优雅的重启或关机:
- 不关闭现有连接(正在运行中的程序)
- 新的进程启动并代替旧进程
- 新的进程接管新的连接
- 连接要随时响应用户的请求,当用户仍在请求旧进程时要保持连接,用户请求新进程时,不可以出现拒绝- - 请求的情况
实现流程
- 替换可执行文件或修改配置文件
- 发送信号量SIGHUP
- 拒绝新连接请求旧进程,但要保证已有连接正常
- 启动新的子进程
系统将新的请求转交给新的子进程
旧进程处理完所有旧连接后正常结束
我的理解:
- 我需要更新服务器,但我不想关闭正在运行着的连接,所以我就在一个子进程上启动了新版本服务器,同时把所有连接的请求都发给这个新的子进程。
- 正在运行的旧连接则继续运行,主进程不再接收新的连接请求,而是等待所有旧连接处理结束。
当所有旧连接处理结束之后,主进程关闭。
实现方案:
- fvbock/endless
- manners
- graceful
- grace
- 使用http.Server的内置Shutdown()方法!(go 1.8以上)
坑:
- 使用endless包时会报错 “undefined: syscall.SIGUSR1”,原因是syscall包里的常量会根据当前操作系统做出选择,而win下的signal信号里没有这些信号。
15. 使用BasicAuth中间件
-
处理简单但安全性低,目前最广泛使用的是OAuth
-
使用方法:
authorized := r.Group("/admin", gin.BasicAuth(gin.Accounts{
“foo”: “bar”,
“austin”: “1234”,
“lena”: “hello2”,
“manu”: “4321”,
})) -
网页访问时会弹出输入窗口,curl使用则是在前面加上“foo:bar@”类似
16. 使用HTTP方法
- 介绍了HTTP方法的使用:GET、POST、PUT、DELETE、PATCH等
17. 使用中间件
- 可以在三种地方使用:全局中间件、路由组中间件、路由中间件
- 使用方法:router.Use(中间件提供的方法)
- 在第15条 BasicAuth中间件的使用中,也可以使用Use()方法
18. 只绑定url查询字符串
- 使用函数 ShouldBindQuery() ,忽略post参数,只取得url查询参数
- 在中间件或handler中使用Goroutine时,必须使用使用上下文副本
- 如果没有使用副本,则上下文会发生改变,例如:
- 路由goroutine,内容是五秒后输出请求的url,此处没有使用副本
- 先请求goroutine,在五秒内如果有其他请求也发送到服务器的话,此时上下文的url已经改变,五秒后输出的url就不是goroutine了而是新的请求url
19. 记录日志
- 将日志记录到文件
- 定义路由日志格式
- 将request body 绑定到不同的结构体
- 【为什么】 c.Request.Body不能被多次调用?
- 【猜测】 Request.Body是流传输,读取一次之后指针Body就会移动到这个流的末尾,从而导致再次读取的时候会报错EOF。但如是如此,为什么其他格式(Query、Form、FormPost…)可以重复调用c.ShouldBind()?
【问题】:这个方法即使没有取到值,仍然不会返回err,官网代码有问题?
但是利用这个方法确实可以多次调用c.Request.Body
20. 支持 Let’s Encrypt
- Let’s Encrypt 是一个免费SSL证书颁发机构
21. 映射查询字符串或表单参数
- 调用方法 C.QueryMap() 和 C.PostFormMap()
- 可以神奇的将传入的参数(形如 ids[a] = 123 & ids[b] = asd)映射为Map(形如 map[ b : asd a : 123 ] )
参考文档:
Gin 官方文档:https://gin-gonic.com/zh-cn/docs/examples/jsonp/
HTTP2 Serve push:https://www.qichengzx.com/2017/07/02/HTTP2-Server-Push.html
JSONP原理详解:http://https://blog.youkuaiyun.com/hansexploration/article/details/80314948
优雅的重启:https://www.cnblogs.com/sunsky303/p/11121409.html