refactor(go)!: 分离练习区与独立项目区
- 将现有练习及 module 文件迁移至 go/practice,保持代码和依赖不变 - 新增 go/projects 项目区说明,更新目录约定与开发命令 BREAKING CHANGE: Go 练习命令需改在 go/practice 目录下执行
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
_ "net/http/pprof"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 来自文章 https://www.cnblogs.com/hwnd/p/20682814
|
||||
func simulateRequest() {
|
||||
timeout := 500 * time.Millisecond
|
||||
ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(timeout))
|
||||
defer cancel()
|
||||
resultCh := make(chan string) // 无缓冲!
|
||||
|
||||
// 启动 worker goroutine 处理"请求"
|
||||
go func() {
|
||||
time.Sleep(time.Duration(rand.Intn(500)+300) * time.Millisecond)
|
||||
select {
|
||||
case <-time.After(timeout):
|
||||
fmt.Println("worker 超时,放弃处理")
|
||||
case <-ctx.Done():
|
||||
case resultCh <- fmt.Sprintf("处理完成,耗时 %dms", rand.Intn(500)+300):
|
||||
|
||||
}
|
||||
}()
|
||||
|
||||
// TODO: 模拟请求取消或超时的情况(比如 500ms 后调用方不再关心结果)
|
||||
// 如果 worker 还没完成,它就 leak 了
|
||||
select {
|
||||
case resultCh := <-resultCh:
|
||||
fmt.Println(resultCh)
|
||||
case <-ctx.Done():
|
||||
fmt.Println("请求方取消了请求")
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
for i := 0; i < 5; i++ {
|
||||
simulateRequest()
|
||||
fmt.Printf("第 %d 个请求处理完毕\n\n", i+1)
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
}
|
||||
fmt.Println("所有请求处理完毕")
|
||||
// 运行后观察:goroutine 数量只增不减
|
||||
http.ListenAndServe(":6060", nil)
|
||||
}
|
||||
Reference in New Issue
Block a user