golang Context应用举例
视频讲解:

Context本质
golang标准库里Context实际上是一个接口(即一种编程规范、 一种约定)。
通过查看源码里的注释,我们得到如下约定:
Done()函数返回一个只读管道,且管道里不存放任何元素(struct{}),所以用这个管道就是为了实现阻塞
Deadline()用来记录到期时间,以及是否到期。
Err()用来记录Done()管道关闭的原因,比如可能是因为超时,也可能是因为被强行Cancel了。
Value()用来返回key对应的value,你可以想像成Context内部维护了一个map。
Context实现
go源码里提供了Context接口的一个具体实现,遗憾的是它只是一个空的Context,什么也没做。
emptyCtx以小写开头,包外不可见,所以golang又提供了Background和TODO这2个函数让我们能获取到emptyCtx。
backgroud和todo明明是一模一样的东西,就是emptyCtx,为什么要搞2个呢?真心求教,知道的同学请在评论区告诉我。
emptyCtx有什么用?创建Context时通常需要传递一个父Context,emptyCtx用来充当最初的那个Root Context。
With Value
当业务逻辑比较复杂,函数调用链很长时,参数传递会很复杂,如下图:

f1产生的参数b要传给f2,虽然f2并不需要参数b,但f3需要,所以b还是得往后传。
如果把每一步产生的新变量都放到Context这个大容器里,函数之间只传递Context,需要什么变量时直接从Context里取,如下图:

f2能从context里取到a和b,f4能从context里取到a、b、c、d。
Timeout
在上期视频

里介绍了超时实现的核心原理,视频中演示的done管道可以用Context的Done()来替代,Context的Done()管道什么时候会被关系呢?2种情况:
1. 通过context.WithCancel创建一个context,调用cancel()时会关闭context.Done()管道。
2. 通过context.WithTimeout创建一个context,当超过指定的时间或者调用cancel()时会关闭context.Done()管道。
Timeout的继承问题
通过context.WithTimeout创建的Context,其寿命不会超过父Context的寿命。比如:
父Context设置了10号到期,5号诞生了子Context,子Context设置了100天后到期,则实际上10号的时候子Context也会到期。
父Context设置了10号到期,5号诞生了子Context,子Context设置了1天后到期,则实际上6号的时候子Context就会到期。
context超时在http请求中的实际应用
定心丸来了,最后说一遍:”context在实践中真的很有用“
客户端发起http请求时设置了一个2秒的超时时间:
服务端从Request里取提context,故意休息10秒钟,同时监听context.Done()管道有没有关闭。由于Request的context是2秒超时,所以服务端还没休息够context.Done()管道就关闭了。
万水千山总是情,给个点赞行不行!