跟着b站https://space.bilibili.com/361469957 杨旭老师学习做的笔记

中间件

什么是中间件

请求————> 中间件 ————> Handler

响应 <———— Middleware <———— Handler

创建中间件

func ListenAndServe(addr string, handler Handler) error
handler 如果是 nil:DefaultServeMux type Handler interface {
ServeHTTP(ResponseWriter, *Request)
} type MyMiddleware struct {
Next http.Handler
}
func(m MyMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// 在 next handler 之前做一些事情
m.Next.ServeHTTP(w, r)
// 在 next handler 之后做一些事情
}

中间件的用途

Logging

安全

请求超时

响应压缩

下面是例子

// 目录下
// middleware文件夹 包含auth.go
// main.go
auth.go package middleware
import "net/http" // 链式结构, Next 设置为 什么,下一个handler 就是什么
// AuthMiddleware ..
type AuthMiddleware struct {
Next http.Handler
} func (am *AuthMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// 如果只有一个中间件,改中间件的字段next 为nil, 交给默认路由器处理
if am.Next == nil {
am.Next = http.DefaultServeMux
}
// 判断auth
auth := r.Header.Get("Authorization")
if auth != "" {
// before 路由
am.Next.ServeHTTP(w, r)
// after 路由
} else {
w.WriteHeader(http.StatusUnauthorized)
}
} main.go
package main import (
"encoding/json"
"net/http"
"timer/goWeb-sql/middleware"
//middleware文件夹的位置,每个人都不一样,自己建的
)
type Company struct {
ID int
Name string
Country string
}
func main(){
http.HandleFunc("/companies", func(w http.ResponseWriter, r *http.Request){
c := Company{
ID: 123,
Name: "goolle",
Country: "USA",
}
// time.Sleep(4*time.Second)
enc := json.NewEncoder(w)
enc.Encode(c)
})
// 通过认证就能获取数据
// 使用中间件
http.ListenAndServe("localhost:8080", new(middleware.AuthMiddleware))
}

GET http://localhost:8080/companies HTTP/1.1 # with auth
GET http://localhost:8080/companies HTTP/1.1
Authorization: root

这个是加上请求上下文的

// 目录下
// middleware文件夹 包含auth.go timeout.go
// main.go timeout.go package middleware import (
"context"
"net/http"
"time"
) type TimeoutMiddleware struct {
Next http.Handler
}
func (tm TimeoutMiddleware) ServeHTTP(w http.ResponseWriter ,r *http.Request){
if tm.Next == nil{
tm.Next = http.DefaultServeMux
} ctx:= r.Context()
ctx,_ = context.WithTimeout(ctx,3*time.Second)
r.WithContext(ctx)
ch:= make(chan struct{})
go func(){
tm.Next.ServeHTTP(w,r)
ch <- struct{}{}
}()
select{
case <- ch:
return
case<- ctx.Done():
w.WriteHeader(http.StatusRequestTimeout)
}
ctx.Done()
} main.go http.HandleFunc("/companies", func(w http.ResponseWriter, r *http.Request) {
c := Company{
ID: 123,
Name: "gggoolle",
Country: "USA",
}
// time.Sleep(4*time.Second) 用来测试的
enc := json.NewEncoder(w)
enc.Encode(c)
})
// 使用中间件
http.ListenAndServe("localhost:8080", &middleware.TimeoutMiddleware{
Next: new(middleware.AuthMiddleware),
})

请求上下文

(例子见上面那个)

请求可能会通过中间件,到达handler,再到model层(数据库,Web Api,文件系统),model层不应该知道在web请求的上下文操作,但是他们需要知道一些重要信息,比如超时停摆。

它可以用于在不同的 Goroutine 之间传递请求特定值、取消信号以及超时截止日期等数据,以协调 Goroutine 之间的操作。

request Context

func(*Request) Context() context.Context
返回当前请求的上下文
func(*Request) WithContext(ctx context.Context) context.Context
基于 Context 进行“修改”,(实际上)创建一个新的 Context

context.Context

type Context interface {
Deadline() (deadline time.Time, ok bool)
//返回 完成工作的截止日期
Done() <-chan struct{}
//返回一个 Channel,这个 Channel 会在当前工作完成或者上下文被取消后关闭,
//多次调用 Done 方法会返回同一个 Channel
Err() error
// 错误
Value(key interface{}) interface{}
// 从 context.Context中获取键对应的值
}
//这些方法都是用于读取,不能进行设置

Context API – 可以返回新 Context

WithCancel(),它有一个 CancelFunc
WithDeadline(),带有一个时间戳(time.Time)
WithTimeout(),带有一个具体的时间段(time.Duration)
WithValue(),在里面可以添加一些值

串联处理器和处理器函数

诸如日志,安全检查和错误处理,为了防止代码重复和代码依赖,可以使用串联技术分隔它们。

也叫做管道处理

输入——》f1 do something ——》f2 do something ——》f3 do something ——》输出

和中间件相像又不一样

串联处理器函数

// http.HandleFunc("/hello",protect(log(hello)))

func hello(w http.ResponseWriter,r *http.Request){
//
}
func log(h http.HandlerFunc) http.HandlerFunc{
return func(w http.ResponseWriter,r *http.Request){
//日志操作
h(w,r)
}
} func protect(h http.HandlerFunc) http.HandlerFunc{
return func(w http.ResponseWriter,r *http.Request){
//一些操作
h(w,r)
}
}

串联处理器

// http.Handle("/hello",protect(log(hello)))
type HelloHandler struct{}
func (h HelloHandler) ServeHttp (w http.ResponseWriter,r *http.Request){ }
func log(h HelloHandler) http.Handler{
return http.HandlerFunc(
func(w http.ResponseWriter,r *http.Request){
//一些操作
h.ServeHttp(w,r)
}
)
}
func protectlog(h HelloHandler) http.Handler{
return http.HandlerFunc(
func(w http.ResponseWriter,r *http.Request){
//一些操作
h.ServeHttp(w,r)
}
)
}

go web学习(四)的更多相关文章

  1. java web 学习四(http协议)

    一.什么是HTTP协议 HTTP是hypertext transfer protocol(超文本传输协议)的简写,它是TCP/IP协议的一个应用层协议,用于定义WEB浏览器与WEB服务器之间交换数据的 ...

  2. Java Web 学习路线

    实际上,如果时间安排合理的话,大概需要六个月左右,有些基础好,自学能力强的朋友,甚至在四个月左右就开始找工作了.大三的时候,我萌生了放弃本专业的念头,断断续续学 Java Web 累计一年半左右,总算 ...

  3. web—第四章css&第五章

     web—第四章css&第五章 终于迎接等待已久的CSS,在没学这个之前,我们只会用一点img,查一点小图片,或者是用style改一下颜色,而且比较麻烦.现在多了个css在文件夹在创建一个cs ...

  4. [原创]java WEB学习笔记95:Hibernate 目录

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  5. Java Web学习系列——Maven Web项目中集成使用Spring

    参考Java Web学习系列——创建基于Maven的Web项目一文,创建一个名为LockMIS的Maven Web项目. 添加依赖Jar包 推荐在http://mvnrepository.com/.h ...

  6. Java Web(十四) 编写MyBookStore项目的总结

    这几天一直没有发博文,原因是在写一个书城的小项目,作为web学习的最后沉淀,接下来就要到框架的学习了. --WH 一.项目介绍 从网上找的一个培训机构的小项目,名称叫做 书城购物网站 吧,其中就是分前 ...

  7. (转)SpringMVC学习(四)——Spring、MyBatis和SpringMVC的整合

    http://blog.csdn.net/yerenyuan_pku/article/details/72231763 之前我整合了Spring和MyBatis这两个框架,不会的可以看我的文章MyBa ...

  8. Spring Boot 项目学习 (四) Spring Boot整合Swagger2自动生成API文档

    0 引言 在做服务端开发的时候,难免会涉及到API 接口文档的编写,可以经历过手写API 文档的过程,就会发现,一个自动生成API文档可以提高多少的效率. 以下列举几个手写API 文档的痛点: 文档需 ...

  9. Java反射:Web学习的灵魂

    反射:Web学习的灵魂 我们从最初的 javac -HelloWorld.java,到面向对象部分,我们可以将Java代码在计算机中经历的阶段分为三部分:Scource源代码阶段 -- Class类对 ...

  10. Web学习之css

    CSS指层叠样式表(Cascading Style Sheets),CSS 是标准的布局语言,用来控制元素的尺寸.颜色.排版.CSS 由 W3C 发明,用来取代基于表格的布局.框架以及其他非标准的表现 ...

随机推荐

  1. python数据类型、变量以及编码和字符串、格式化

    1.数据类型包括整型.浮点型.字符串.布尔型. 整数如果位数太多可以用_隔开,浮点数可以用科学记数法表示,字符串要用单引号或者双引号括起来,布尔型的值只能为True和False 2.变量可以由数字.字 ...

  2. 从零开始学Vue(二~三)—— Vue 实例 / 模板语法(插值、指令)

    概述 vue.js作为现在笔记热门的JS框架,使用比较简单易上手,也成为很多公司首选的JS框架. 但是对于初学者可能学起来有些麻烦,所以推出<从零开始学Vue>系列博客,本系列计划推出19 ...

  3. 频繁设置CGroup触发linux内核bug导致CGroup running task不调度

    1. 说明 1> 本篇是实际工作中linux上碰到的一个问题,一个使用了CGroup的进程处于R状态但不执行,也不退出,还不能kill,经过深入挖掘才发现是Cgroup的内核bug 2>发 ...

  4. 《简化iOS APP上架流程,App Uploader助你搞定!》

    转载;http://kxdang.com/topic/appuploader/questions.html Appuploader 常见错误及解决方法   问题解决秘籍 遇到问题,第一个请登录苹果开发 ...

  5. shell执行一个程序过程

    1:shell调用执行程序或脚本 2:unix内核启动一个新的进程,在该进程中执行所指定的程序. 3:如果是编译型程序,内核成执行,如果无法执行指定的程序,返回"not executable ...

  6. Python-获取Local Storage和Session Storage

    一.简介 LocalStorage 是只读的.数据存储也是跨浏览器会话.LocalStorage 类似于SessionStorage. 区别在于,数据存储在 LocalStorage 是无期限的,而当 ...

  7. 搭建SpringBoot项目依赖和配置快速篇

    maven依赖及一些配置 这里主要是搭建项目常用到的maven依赖以及搭建项目会需要用到的一些配置文件,可能下面这些依赖还不是很全,但是应该会满足日常大部分的需求了 Spring Spring项目的依 ...

  8. MacOS 环境下 VSCode 的 C++ 环境搭建

    编译器安装 编译器可以选择 Clang 或者 GCC,在 MacOS 上 Clang 的安装更为简单一些. Clang(推荐) 打开终端输入命令, clang -v 查看是否已经安装. 如果已经安装, ...

  9. XUnit数据共享与并行测试

    引言 在单元或者集成测试的过程中,需要测试的用例非常多,如果测试是一条一条过,那么需要花费不少的时间.从 V2 开始,默认情况下 XUnit 自动配置并行(参考资料),大大提升了测试速度.本文将对 A ...

  10. 2022-07-17:1、2、3...n-1、n、n、n+1、n+2... 在这个序列中,只有一个数字有重复(n)。 这个序列是无序的,找到重复数字n。 这个序列是有序的,找到重复数字n。

    2022-07-17:1.2.3-n-1.n.n.n+1.n+2- 在这个序列中,只有一个数字有重复(n). 这个序列是无序的,找到重复数字n. 这个序列是有序的,找到重复数字n. 答案2022-07 ...