GOland的context的使用

devtools/2025/2/12 0:45:36/

超时控制

在 HTTP 请求、数据库查询或 RPC 调用等操作中,防止请求长时间阻塞。

package mainimport ("context""fmt""time"
)func main() {// 设置 2 秒超时ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)defer cancel() // 确保超时后释放资源result := make(chan string)go func() {time.Sleep(3 * time.Second) // 模拟耗时任务result <- "任务完成"}()select {case res := <-result:fmt.Println(res)  // 如果 `result` 先返回数据,就打印结果case <-ctx.Done():fmt.Println("任务超时,取消操作") // 如果 `ctx.Done()` 先触发,说明超时了}
}

context.WithTimeout() 允许在设定时间后自动取消操作,避免 goroutine 长时间阻塞

手动取消

如果一个主 goroutine 需要通知子 goroutine 停止执行,可以使用 context.WithCancel()

package mainimport ("context""fmt""time"
)func worker(ctx context.Context) {for {select {case <-ctx.Done():fmt.Println("收到取消信号,退出")returndefault:fmt.Println("工作中...")time.Sleep(500 * time.Millisecond)}}
}func main() {ctx, cancel := context.WithCancel(context.Background())go worker(ctx)time.Sleep(2 * time.Second)fmt.Println("取消任务")cancel() // 发送取消信号time.Sleep(1 * time.Second) // 等待 goroutine 退出
}在 TCP 服务器中,我们可能需要在主程序退出时,通知所有客户端断开连接。package mainimport ("context""fmt""net""time"
)func handleConnection(ctx context.Context, conn net.Conn) {defer conn.Close()for {select {case <-ctx.Done():fmt.Println("断开客户端连接:", conn.RemoteAddr())returndefault:time.Sleep(1 * time.Second) // 模拟处理fmt.Println("服务客户端:", conn.RemoteAddr())}}
}func main() {ctx, cancel := context.WithCancel(context.Background())ln, err := net.Listen("tcp", ":8080")if err != nil {fmt.Println("监听失败:", err)return}defer ln.Close()go func() {for {conn, err := ln.Accept()if err != nil {fmt.Println("接受连接失败:", err)continue}go handleConnection(ctx, conn)}}()time.Sleep(10 * time.Second) // 服务器运行 10 秒fmt.Println("关闭服务器,断开所有连接")cancel() // 发送取消信号,所有连接都会断开time.Sleep(2 * time.Second) // 等待 goroutine 退出fmt.Println("服务器已关闭")
}

context.WithCancel() 适用于 任务需要手动终止 的场景,如定期任务、消息队列消费等。

传递请求作用域的数据

可以用 context.WithValue() 传递 请求相关的元数据,比如 用户身份信息、trace ID

package mainimport ("context""fmt"
)// 定义一个键的类型,避免键冲突
type contextKey stringfunc processRequest(ctx context.Context) {uid := ctx.Value(contextKey("userID"))fmt.Println("处理请求的用户 ID:", uid)
}func main() {ctx := context.WithValue(context.Background(), contextKey("userID"), 12345)processRequest(ctx)
}

context.WithValue() 适用于 日志追踪、用户身份验证 等场景,但不建议传递大数据结构(会影响性能)。

与 HTTP 服务器结合

在 Web 服务器中,Go 的 http.Request 自带 Context() 方法,可以获取请求的 context,用于控制请求生命周期

package mainimport ("context""fmt""net/http""time"
)func handler(w http.ResponseWriter, r *http.Request) {ctx := r.Context()fmt.Println("处理请求")select {case <-time.After(3 * time.Second):fmt.Fprintln(w, "请求处理完成")case <-ctx.Done():fmt.Fprintln(w, "请求取消")}
}func main() {http.HandleFunc("/", handler)server := &http.Server{Addr: ":8080",}go func() {time.Sleep(2 * time.Second)server.Shutdown(context.Background()) // 2 秒后关闭服务器}()fmt.Println("服务器启动在 8080 端口")if err := server.ListenAndServe(); err != nil {fmt.Println("服务器已关闭")}
}

当客户端断开连接,ctx.Done() 会触发,避免继续执行无用的操作。


http://www.ppmy.cn/devtools/157677.html

相关文章

(原创,可用)SSH实现内外网安全穿透(安全不怕防火墙)

目前有A、B终端和一台服务器&#xff0c;A、B机器不能直接访问&#xff0c;服务器不能直接访问A、B终端但是A、B终端可以访问服务器&#xff0c;这个场景很像我们有一台电脑在单位内网&#xff0c;外机器想访问内网系统&#xff0c;可能大家目前想到的就是frp之类穿透工具&…

一口气入门前端——HTML5入门

HTML5 1.1 HTML 介绍 HTML&#xff08;超文本标记语言&#xff09;是一种用于 Web 开发的标记语言&#xff0c;主要用来格式化和显示网页内容。可以将其视为一种文本文件&#xff0c;浏览器能够读取该文本文件并显示其中的内容。HTML支持多种元素&#xff08;也称作标签&…

律所录音证据归集工具:基于PyQt6与多线程的自动化音频管理解决方案

在律所日常工作中&#xff0c;音频证据的整理与归集是一个高频且复杂的任务。面对大量的案件录音文件&#xff0c;如何实现快速且准确的分类与存档&#xff0c;成为了律所提高效率、降低出错率的关键。本文将通过技术角度解析一款名为律所录音证据归集工具的项目&#xff0c;详…

Mysql-增删改查(知识点总结)

一.增(create table/database ,Insert into) &#xff08;1&#xff09;创建表 CREATE TABLE students ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50) NOT NULL, age INT, grade DECIMAL(5,2) ); -- 创建students表&#xff0c;包含自增ID、姓名、年…

让文物“活”起来,以3D数字化技术传承文物历史文化!

文物&#xff0c;作为不可再生的宝贵资源&#xff0c;其任何毁损都是无法逆转的损失。然而&#xff0c;当前文物保护与修复领域仍大量依赖传统技术&#xff0c;同时&#xff0c;文物管理机构和专业团队的力量相对薄弱&#xff0c;亟需引入数字化管理手段以应对挑战。 积木易搭…

Kotlin 使用 Chrome 无头浏览器

1. 概念 无头浏览器在类似于流行网络浏览器的环境中提供对网页的自动控制&#xff0c;但是通过命令行界面或使用网络通信来执行。 它们对于测试网页特别有用&#xff0c;因为它们能够像浏览器一样呈现和理解超文本标记语言&#xff0c;包括页面布局、颜色、字体选择以及JavaSc…

UITableView的复用原理

UITableView复用的基本原理是Cell复用机制&#xff0c;它通过重用已经创建的Cell来减少内存开始并提高性能&#xff0c;避免频繁创建和销毁Cell。 复用的流程 1.队列管理 UITableView维护一个可复用队列&#xff08;reuse queue&#xff09;&#xff0c;存储离屏的UITableVi…

微服务日志查询难解决方案-EFK

前言 在微服务项目中&#xff0c;日志查询难是一个常见问题&#xff0c;主要原因包括&#xff1a;日志分散&#xff1a;微服务实例分布在多个节点或容器中&#xff0c;日志存储位置分散。格式不统一&#xff1a;不同服务可能使用不同的日志格式&#xff0c;难以统一查询。调用…