当前位置: 首页 > news >正文

Golang学习笔记:context的使用场景

context在Go语言中是一个非常重要的知识点,在使用场景和面试问答中经常被提及到,如果想学习其原理知识,可以参考, 这篇文章只做使用场景总结。
context包为协程间传递信号提供了一些方法,用于管理请求生命周期和控制并发操作,context的使用场景有以下几个:

控制请求的生命周期

在处理HTTP请求时,通常需要确保请求处理过程中能够及时取消、超时或结束。尤其当请求涉及到多个下游服务调用时,若一个服务响应缓慢或失败,必须取消所有其他正在进行的操作。
示例:

func handler(w http.ResponseWriter, r *http.Request) {ctx := r.Context()resultChan := make(chan string, 1) // 使用缓冲通道避免 goroutine 泄漏// 启动 goroutine 执行耗时操作go func() {// 模拟耗时操作select {case <-time.After(2 * time.Second):// 检查父 context 是否已经结束select {case resultChan <- "operation completed successfully":log.Println("Operation completed and result sent")case <-ctx.Done():log.Println("Operation completed but context was canceled, discarding result")}case <-ctx.Done():log.Println("Operation canceled before completion")// 不发送结果,因为 context 已取消}}()// 等待结果或取消信号select {case <-ctx.Done():// 请求取消或超时switch ctx.Err() {case context.Canceled:log.Println("Request was canceled by client")http.Error(w, "request canceled", http.StatusRequestTimeout)case context.DeadlineExceeded:log.Println("Request timeout")http.Error(w, "request timeout", http.StatusGatewayTimeout)default:log.Printf("Context error: %v", ctx.Err())http.Error(w, "request failed", http.StatusInternalServerError)}returncase result := <-resultChan:// 正常返回结果log.Println("Returning successful result")w.Header().Set("Content-Type", "text/plain; charset=utf-8")fmt.Fprintln(w, result)}
}

处理超时和截止时间

当处理需要网络调用或长时间运行的操作时,设定一个超时时间或截止日期是很重要的。context可以传递一个超时或截止日期,自动取消操作,避免资源浪费。
示例:

package mainimport ("context""fmt""time"
)func main() {ctx := context.Background()fmt.Println(fetchData(ctx))
}func fetchData(ctx context.Context) (string, error) {ctx, cancel := context.WithTimeout(ctx, 2*time.Second)defer cancel()ch := make(chan string, 1)go func() {//模拟耗时操作time.Sleep(3 * time.Second)ch <- "data"}()select {case <-ctx.Done():fmt.Println("Done")return "", ctx.Err()case result := <-ch:fmt.Println("result")return result, nil}
}
package mainimport ("context""fmt""time"
)func main() {// 设置一个具体的截止时间deadline := time.Now().Add(3 * time.Second)ctx, cancel := context.WithDeadline(context.Background(), deadline)defer cancel() // 重要:确保资源被释放// 检查截止时间if dl, ok := ctx.Deadline(); ok {fmt.Printf("Deadline set to: %v\n", dl.Format("15:04:05.000"))}// 等待 context 超时select {case <-time.After(5 * time.Second):fmt.Println("Operation completed")case <-ctx.Done():fmt.Printf("Context canceled: %v\n", ctx.Err())}
}

传递元数据

在微服务架构中,需要在服务之间传递一些与请求相关的元数据,例如认证信息、分布日志ID等,context提供了传递这些信息的方式。
示例:

func main() {ctx := context.Background()ctx = context.WithValue(ctx, "requestID", "12345")processRequest(ctx)
}func processRequest(ctx context.Context) {reqID := ctx.Value("requestID")fmt.Println("Request ID:", reqID)
}

协同工作

在复杂的并发任务中,不同的协程可能需要相互协作,或需要再特定条件下取消其他协程,context可以用于协同工作,统一管理多个协程的状态。

func main() {ctx, cancel := context.WithCancel(context.Background())go worker(ctx, "worker1")go worker(ctx, "worker2")time.Sleep(1 * time.Second)cancel() // 取消所有工作time.Sleep(1 * time.Second)
}func worker(ctx context.Context, name string) {for {select {case <-ctx.Done():fmt.Println(name, "stopped")returndefault:fmt.Println(name, "working")time.Sleep(500 * time.Millisecond)}}
}

限制并发数量

在特定场景下,需要限制并发执行的协程数量,避免过度消耗系统资源,context可以与信号量或sync.WaitGroup一起使用来限制并发数量。

func main() {ctx, cancel := context.WithCancel(context.Background())defer cancel()sem := make(chan struct{}, 3) // 限制并发数为3var wg sync.WaitGroupfor i := 0; i < 10; i++ {wg.Add(1)go func(i int) {defer wg.Done()sem <- struct{}{} // 获取信号defer func() { <-sem }() // 释放信号worker(ctx, i)}(i)}wg.Wait()
}func worker(ctx context.Context, id int) {select {case <-ctx.Done():fmt.Printf("worker %d canceled\n", id)returndefault:fmt.Printf("worker %d working\n", id)time.Sleep(1 * time.Second)}
}
http://www.dtcms.com/a/423949.html

相关文章:

  • 带有客户案例的网站广州专业网站建设报价
  • 昆明微信网站建设软件开发模型有几种并简述其特点
  • 高效实现实体删除的宏解决方案:使用Rust宏优化删除操作
  • Rust泛型详解
  • 官方手表网站网站专题分类
  • 新乡网站建设方案搜狗网址大全下载安装
  • 关于可视化卷积核和特征图的深度理解
  • 【mysql】Mybatisplus BINARY {0} LIKE CONCAT(‘%‘, {1}, ‘%‘)写这句话是什么意思
  • 开发避坑指南(59):Vue3中高效删除数组元素的方法
  • wordpress建站要用模板吗wordpress搜索筛选
  • 安卓 WPS Office v18.21.0 国际版
  • 衡阳网站推广优化公司行业网站开发运营方案
  • 临海房产中介网站如何制作网站平台管理
  • 做网站多少人建e室内设计网官网平面图
  • git mere 错误后的回滚处理
  • Java开发入门(一)--- JDK与环境变量配置
  • 最好的营销型网站建设公司报电子商务(网站建设与运营)
  • 从0到1制作一个go语言游戏服务器(二)web服务搭建
  • 网站使用流程图昆明网站建设天锐科技
  • (uniapp)基于vue3父子组件间传递参数与方法
  • 铁岭开原网站建设高中课程免费教学网站
  • 高校网站群建设方案网站建设目录结构设计
  • 静态网站源码野花韩国视频在线观看免费高清
  • Windows下NVM保姆级指南:安装、切换版本、指定路径+淘宝镜像配置,一次搞定!
  • 杭州营销型网站建设杭州租车网站建设
  • 网站开发基础知识网站开发怎么连接sqlserver
  • 基于AC6366C做AI语音鼠标
  • 刘诗雯现身TCL品牌活动,雷鸟34Q9显示器同台竞技
  • 东莞百域网站建设公司手机网站开发屏幕尺寸一般是多少
  • 理财经理如何提高职场技能实现晋升