context基本使用示例
约 622 字大约 2 分钟
2025-05-17
测试代码
package main
import (
"context"
"fmt"
"github.com/gin-contrib/pprof"
"github.com/gin-gonic/gin"
"github.com/gorilla/handlers"
_ "github.com/mkevac/debugcharts"
"log"
"net/http"
"time"
)
func startGoroutine(ctx context.Context, cnt int) {
if cnt <= 0 {
cnt = 100
}
for i := 0; i < 100; i++ {
go func(cancelCtx context.Context, idx int) {
for {
hasFinish := false
select {
case <-cancelCtx.Done():
hasFinish = true
fmt.Println("goroutine ", idx, " is finished ", time.Now().Format(time.DateTime))
break
default:
time.Sleep(time.Second)
fmt.Println("goroutine ", idx, " is running")
}
if hasFinish {
break
}
}
}(ctx, i)
}
}
func main() {
r := gin.Default()
pprof.Register(r)
// 测试取消context
r.GET("/test/context/cancel", func(c *gin.Context) {
ctx, cancel := context.WithCancel(context.Background())
startGoroutine(ctx, 100)
// 休眠5s后取消, 模拟主动取消
time.Sleep(time.Second * 5)
cancel()
// 额外休眠5s, 为了明确显示出, 后台协程退出是因为主动取消, 而不是因为函数执行完成退出
time.Sleep(time.Second * 5)
fmt.Println("all goroutine is finished ", time.Now().Format(time.DateTime))
c.JSON(http.StatusOK, gin.H{"msg": "ok! cancel"})
})
// 测试timeout
r.GET("/test/context/timeout", func(c *gin.Context) {
// 一个 10s 超时的context
ctx, _ := context.WithTimeout(context.Background(), time.Second*10)
startGoroutine(ctx, 100)
// 休眠12s后返回, 模拟超时
time.Sleep(time.Second * 12)
fmt.Println("模拟超时完成 ", time.Now().Format(time.DateTime))
c.JSON(http.StatusOK, gin.H{"msg": "ok! timeout"})
})
go func() {
log.Fatal(http.ListenAndServe(":8888", handlers.CompressHandler(http.DefaultServeMux)))
}()
r.Run(":8080")
}
基础信息
# 常看pprof相关信息实时变化
http://localhost:8888/debug/charts/
# 测试cancelContext
http://localhost:8080/test/context/cancel
# 测试timeout
http://localhost:8080/test/context/timeout
CancelContext说明
打开pprof监控页面之后, 访问测试取消接口, 可以看到有100个goroutine在运行, 然后10s后取消, 可以看到100个goroutine都已经退出了
终端会有如下信息输出:
.....
goroutine 40 is running
goroutine 40 is finished 2025-05-17 23:10:13
goroutine 13 is running
goroutine 13 is finished 2025-05-17 23:10:13
goroutine 95 is finished 2025-05-17 23:10:13
goroutine 50 is finished 2025-05-17 23:10:13
all goroutine is finished 2025-05-17 23:10:18
所有协程取消退出之后, 再次休眠5s后, 才退出请求方法, 说明后台协程的退出, 是程序主动取消的, 协程监控如下:

TimeoutContext说明
打开pprof监控页面之后, 访问测试取消接口, 可以看到有100个goroutine在运行, 然后10s后取消, 可以看到100个goroutine都已经退出了
终端会有如下信息输出:
.....
goroutine 14 is running
goroutine 14 is finished 2025-05-17 23:17:41
goroutine 74 is running
goroutine 74 is finished 2025-05-17 23:17:41
goroutine 89 is finished 2025-05-17 23:17:41
模拟超时完成 2025-05-17 23:17:43
超时context配置的超时时间是10s, 但是程序在12s后才退出, 说明后台协程的退出, 是程序主动超时取消的, 协程监控如下
