深入理解Golang中的Context包

本文深入介绍了Golang中的Context包,首先讲解了Goroutine和Channel的基本概念及其在并发编程中的作用,接着阐述了Context在多Goroutine通信和请求生命周期管理中的应用场景,最后详细解析了Context的设计原理、接口及其使用原则,强调了Context在并发控制和资源回收方面的关键作用。
摘要由CSDN通过智能技术生成

context.Context是Go语言中独特的设计,在其他编程语言中我们很少见到类似的概念。context.Context深度支持Golang的高并发。

1. Goroutine和Channel

在理解context包之前,应该首先熟悉Goroutine和Channel,能加深对context的理解。

1.1 Goroutine

Goroutine是一个轻量级的执行线程,多个Goroutine比一个线程轻量,所以管理Goroutine消耗的资源相对更少。Goroutine是Go中最基本的执行单元,每一个Go程序至少有一个Goroutine:主Goroutine。程序启动时会自动创建。为了能更好的理解Goroutine,先来看一看线程Thread与协程Coroutine的概念。

  • 线程(Thread)
    线程是一种轻量级进程,是CPU调度的最小单位。一个标准的线程由线程ID当前指令指针(PC)寄存器集合堆栈组成。线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源,但它可与同属于一个进程的其他线程共享进程所拥有的全部资源。线程拥有自己独立的栈和共享的堆,共享堆,不共享栈 线 程 的 切 换 一 般 由 操 作 系 统 调 度 \color{red}{线程的切换一般由操作系统调度} 线
  • 协程(Coroutine)
    协程又称为微线程,与子例程一样,协程也是一种程序组建,相对子例程而言,协程更为灵活,但在实践中使用没有子例程那样广泛。和线程类似,共享堆,不共享栈, 协 程 的 切 换 一 般 由 程 序 员 在 代 码 中 显 式 控 制 \color{red}{协程的切换一般由程序员在代码中显式控制} 。他避免了上下文切换的额外耗费,兼顾了多线程的优点,简化了高并发程序的复杂。

Goroutine和其他语言的协程(coroutine)在使用方式上类似,但从字面意义上来看不同(一个是Goroutine,一个是coroutine),再就是协程是一种协作任务控制机制,在最简单的意义上,协程不是并发的,而Goroutine支持并发的。因此Goroutine可以理解为一种Go语言的协程。同时,Gorotine可以运行在一个或多个线程上

1.2 使用Goroutine示例

func Hello()  {
   
    fmt.Println("hello everybody , I'm lineshen")
}

func main()  {
   
    go Hello()
    fmt.Println("Golang-Gorontine Example")
}

在该代码片段中,使用go又开启了一个Goroutine执行Hello方法,其运行结果如下:

Golang-Gorontine Example

从执行结果上,直观的看,我们的程序似乎没有执行Goroutine的Hello方法。出现这个问题的原因是我们启动的主Goroutine在main执行完就退出了,所以为了main等待Hello-Goroutine执行完,就需要一些方法,让Hello-Goroutine告诉main执行完了,这里就需要通道Channel了。

1.3 Channel

Channel就是多个Goroutine 之间的沟通渠道。当我们想要将结果或错误,或任何其他类型的信息从一个 goroutine 传递到另一个 goroutine 时就可以使用通道。通道是有类型的,可以是 int 类型的通道接收整数或错误类型的接收错误等。

假设有个 int 类型的通道 ch,如果想发一些信息到这个通道,语法是 ch <- 1,如果想从这个通道接收一些信息,语法就是 var := <-ch。这将从这个通道接收并存储值到 var 变量。

通过改善1.2中的代码片段,证明通道的使用确保了 goroutine 执行完成并将值返回给 main 。

func Hello(ch chan int)  {
   
    fmt.Println("hello everybody , I'm lineshen")
    ch <- 1
}

func main()  {
   
    ch := make(chan int)
    go Hello(ch)
    <-ch
    fmt.Println("Golang-Gorontine Example")
}

执行结果如下:

hello everybody , I'm lineshen
Golang-Gorontine Example

这里我们使用通道进行等待,这样main就会等待Hello-Goroutine执行完。熟悉了Goroutine、Channel的概念了,就很好理解Context了。

2. Context应用场景

熟悉了Goroutine、Channel的概念,先看一个请求服务场景示例:

func main()  {
   
    http.HandleFunc("/", SayHello) // 设置访问的路由
    log.Fatalln(http.ListenAndServe(":8080",nil))
}

func SayHello(writer http.ResponseWriter, request *http.Request)  {
   
    fmt.Println
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值