转载深入理解Golang中的Context包_沈子恒的博客-优快云博客_golang context
线程(Thread): 线程是轻量级进程,是cpu 调度的最小单位。一个标准的线程由线程ID,当前指令指针(PC) , 寄存器集合和堆栈组成。线程是进程中的一个实体被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源,但它可与属于一个进程的其他线程共享所拥有的全部资源。线程拥有自己独立的栈和共享的堆,共享堆,不共享栈线程的切换一般由操作系统调度
协程(Goroutine): 协程又称微线程,与子例程一样,协程也是一种程序组件,相对子例程而言,协程更为灵活,协程共享堆,不共享栈,协程的切换一般由程序员在代码中显式控制。他避免了上下文切换的额外耗费,兼顾了多线程的有点,简化了程序的复杂,Gorotine可以运行在一个或多个线程上。
func main() {
http.HandleFunc("/", SayHello) // 设置访问的路由
log.Fatalln(http.ListenAndServe(":9090", nil))
}
func SayHello(writer http.ResponseWriter, request *http.Request) {
fmt.Println(&request)
go func() {
for range time.Tick(time.Second) {
select {
case <-request.Context().Done():
fmt.Println("request is out ")
return
default:
fmt.Println("Current request is in progress " + time.Now().Format("2006-01-02 15:04:05"))
}
}
}()
time.Sleep(2 * time.Second)
fmt.Println("time = ", time.Now().Format("2006-01-02 15:04:05"))
writer.Write([]byte("Hi, New Request Come"))
}
context包可以提供一个请求从API请求边界到各goroutine的请求域数据传递、取消信号及截至时间等能力。
每一个 Context 都会从最顶层的 Goroutine 一层一层传递到最下层,这也是 Golang 中上下文最常见的使用方式,如果没有 Context,当上层执行的操作出现错误时,下层其实不会收到错误而是会继续执行下去:
当最上层的 Goroutine 因为某些原因执行失败时,下两层的 Goroutine 由于没有接收到这个信号所以会继续工作;但是当我们正确地使用 Context 时,就可以在下层及时停掉无用的工作减少额外资源的消耗:
这其实就是 Golang 中上下文的最大作用,在不同 Goroutine 之间对信号进行同步避免对计算资源的浪费,与此同时 Context 还能携带以请求为作用域的键值对信息。