惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

N
Netflix TechBlog - Medium
V
Vulnerabilities – Threatpost
Google Online Security Blog
Google Online Security Blog
Hugging Face - Blog
Hugging Face - Blog
L
LINUX DO - 热门话题
云风的 BLOG
云风的 BLOG
P
Proofpoint News Feed
D
Docker
C
Cyber Attacks, Cyber Crime and Cyber Security
MyScale Blog
MyScale Blog
P
Palo Alto Networks Blog
T
Tenable Blog
P
Privacy International News Feed
Google DeepMind News
Google DeepMind News
小众软件
小众软件
Cisco Talos Blog
Cisco Talos Blog
aimingoo的专栏
aimingoo的专栏
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
A
Arctic Wolf
C
Cybersecurity and Infrastructure Security Agency CISA
C
Cisco Blogs
T
Threat Research - Cisco Blogs
NISL@THU
NISL@THU
The Hacker News
The Hacker News
Project Zero
Project Zero
AWS News Blog
AWS News Blog
Simon Willison's Weblog
Simon Willison's Weblog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
T
Threatpost
V
Visual Studio Blog
The GitHub Blog
The GitHub Blog
The Cloudflare Blog
Last Week in AI
Last Week in AI
Jina AI
Jina AI
Cyberwarzone
Cyberwarzone
The Register - Security
The Register - Security
C
CXSECURITY Database RSS Feed - CXSecurity.com
Vercel News
Vercel News
D
Darknet – Hacking Tools, Hacker News & Cyber Security
MongoDB | Blog
MongoDB | Blog
U
Unit 42
Scott Helme
Scott Helme
A
About on SuperTechFans
WordPress大学
WordPress大学
F
Fortinet All Blogs
大猫的无限游戏
大猫的无限游戏
G
GRAHAM CLULEY
Latest news
Latest news
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
S
Schneier on Security

博客园 - 汉克书

新工作新气象 记录一些skill的网站 重构代码的思路想法 内网服务器如何跟服务端通信 增加一下git提交记录的关键词 水一篇博文 文件服务器对于devops的用处 git信息提交错误,进行修改 还是没啥东西写的,写点DevOps的想法 突然想了一些“思路”问题。提出的一些想法 就是想吐槽一下信创 这个月好像没啥可以写的,rest client mac和linux终端显示分支 继续一个日常 devops 这个月又没什么东西可以写的,就写个harbor的arm版本获取地方吧 写一个日常吧 docker 在x86运行arm容器 ansible的最佳实践 临时用的
ai生成一段学习golang的select、context、go、channel的代码
汉克书 · 2025-12-05 · via 博客园 - 汉克书
package main

import (
	"context"
	"fmt"
	"math/rand"
	"sync"
	"time"
)

// 模拟的数据结构
type UserInfo struct {
	ID   int
	Name string
	Age  int
}

type OrderHistory struct {
	Orders []string
	Total  float64
}

type Recommendations struct {
	Items []string
}

// 模拟的数据库/API客户端
type APIClient struct{}

// 1. 获取用户信息(模拟数据库查询)
func (c *APIClient) GetUserInfo(ctx context.Context, userID int) (*UserInfo, error) {
	select {
	case <-ctx.Done():
		fmt.Println("GetUserInfo: 请求被取消")
		return nil, ctx.Err()
	case <-time.After(time.Duration(rand.Intn(2000)) * time.Millisecond): // 模拟0-2秒延迟
		return &UserInfo{ID: userID, Name: fmt.Sprintf("用户%d", userID), Age: 25}, nil
	}
}

// 2. 获取订单历史(模拟外部API调用)
func (c *APIClient) GetOrderHistory(ctx context.Context, userID int) (*OrderHistory, error) {
	// 模拟10%的失败率
	if rand.Intn(10) == 0 {
		return nil, fmt.Errorf("订单服务暂时不可用")
	}

	select {
	case <-ctx.Done():
		fmt.Println("GetOrderHistory: 请求被取消")
		return nil, ctx.Err()
	case <-time.After(time.Duration(800+rand.Intn(1200)) * time.Millisecond): // 0.8-2秒延迟
		return &OrderHistory{
			Orders: []string{"订单A", "订单B", "订单C"},
			Total:  299.99,
		}, nil
	}
}

// 3. 获取推荐内容(模拟缓存查询)
func (c *APIClient) GetRecommendations(ctx context.Context, userID int) (*Recommendations, error) {
	select {
	case <-ctx.Done():
		fmt.Println("GetRecommendations: 请求被取消")
		return nil, ctx.Err()
	case <-time.After(time.Duration(rand.Intn(1000)) * time.Millisecond): // 0-1秒延迟
		return &Recommendations{
			Items: []string{"推荐商品A", "推荐商品B", "推荐商品C"},
		}, nil
	}
}

// 聚合器:并发获取所有数据
type Aggregator struct {
	client *APIClient
}

// Result 包装每个请求的结果
type Result struct {
	DataType string      // 数据类型
	Data     interface{} // 实际数据
	Err      error       // 错误信息
}

// AggregateUserData 并发聚合用户数据
func (a *Aggregator) AggregateUserData(ctx context.Context, userID int) map[string]interface{} {
	// 创建带有超时的上下文(3秒后超时)
	ctx, cancel := context.WithTimeout(ctx, 3*time.Second)
	defer cancel() // 确保释放资源

	// 创建带缓冲的channel,避免goroutine泄漏
	resultChan := make(chan Result, 3)

	var wg sync.WaitGroup

	// 1. 启动获取用户信息的goroutine
	wg.Add(1)
	go func() {
		defer wg.Done()
		userInfo, err := a.client.GetUserInfo(ctx, userID)
		resultChan <- Result{"user_info", userInfo, err}
	}()

	// 2. 启动获取订单历史的goroutine
	wg.Add(1)
	go func() {
		defer wg.Done()
		orders, err := a.client.GetOrderHistory(ctx, userID)
		resultChan <- Result{"order_history", orders, err}
	}()

	// 3. 启动获取推荐内容的goroutine
	wg.Add(1)
	go func() {
		defer wg.Done()
		recommendations, err := a.client.GetRecommendations(ctx, userID)
		resultChan <- Result{"recommendations", recommendations, err}
	}()

	// 独立的goroutine等待所有任务完成并关闭channel
	go func() {
		wg.Wait()
		close(resultChan)
	}()

	// 主goroutine收集结果
	results := make(map[string]interface{})

	// 关键部分:使用select监听多个channel
	for {
		select {
		case <-ctx.Done():
			// 上下文被取消或超时
			fmt.Printf("\n聚合请求超时或被取消: %v\n", ctx.Err())

			// 尝试收集已经完成的结果
			fmt.Println("已收集到的部分结果:")
			for k, v := range results {
				fmt.Printf("  %s: %v\n", k, v)
			}

			// 添加超时标记
			results["timeout"] = true
			return results

		case result, ok := <-resultChan:
			if !ok {
				// channel已关闭,所有结果收集完成
				fmt.Println("\n所有请求完成!")
				return results
			}

			// 处理单个结果
			if result.Err != nil {
				fmt.Printf("获取 %s 失败: %v\n", result.DataType, result.Err)
				results[result.DataType+"_error"] = result.Err.Error()
			} else {
				fmt.Printf("成功获取 %s\n", result.DataType)
				results[result.DataType] = result.Data
			}
		}
	}
}

func main() {
	fmt.Println("=== Go并发编程示例:API数据聚合 ===")

	client := &APIClient{}
	aggregator := &Aggregator{client: client}

	// 测试1: 正常情况
	fmt.Println("测试1: 正常请求(3秒超时)")
	fmt.Println("------------------------")
	start := time.Now()
	results := aggregator.AggregateUserData(context.Background(), 123)
	elapsed := time.Since(start)

	fmt.Printf("\n总耗时: %v\n", elapsed)
	fmt.Printf("收集到的数据类型数量: %d\n\n", len(results))

	// 显示部分结果
	if userInfo, ok := results["user_info"]; ok {
		fmt.Printf("用户信息: %+v\n", userInfo)
	}

	// 测试2: 模拟手动取消
	fmt.Println("\n\n测试2: 手动取消请求")
	fmt.Println("-------------------")
	ctx, cancel := context.WithCancel(context.Background())

	// 启动一个goroutine在500ms后取消请求
	go func() {
		time.Sleep(500 * time.Millisecond)
		fmt.Println("\n发送取消信号...")
		cancel()
	}()

	start = time.Now()
	results = aggregator.AggregateUserData(ctx, 456)
	fmt.Println("results", results)
	elapsed = time.Since(start)

	fmt.Printf("\n请求在 %v 后被取消\n", elapsed)

	// 测试3: 模拟外部中断
	fmt.Println("\n\n测试3: 模拟外部中断处理")
	fmt.Println("-----------------------")

	interruptChan := make(chan struct{}, 1)

	// 创建一个可以响应中断的上下文
	ctx, cancel = context.WithCancel(context.Background())
	defer cancel()

	// 模拟外部中断(如用户按Ctrl+C)
	go func() {
		time.Sleep(700 * time.Millisecond)
		fmt.Println("\n[系统] 收到中断信号")
		interruptChan <- struct{}{}
	}()

	// 启动聚合请求
	go func() {
		results := aggregator.AggregateUserData(ctx, 789)
		fmt.Printf("\n中断测试结果: %d个数据项\n", len(results))
	}()

	// 监听中断信号
	select {
	case <-interruptChan:
		fmt.Println("[系统] 正在取消所有请求...")
		cancel()                           // 取消上下文
		time.Sleep(100 * time.Millisecond) // 给goroutine一些时间响应
	case <-time.After(2 * time.Second):
		fmt.Println("[系统] 未收到中断信号")
	}

	time.Sleep(1 * time.Second) // 等待所有输出完成
	fmt.Println("\n=== 示例结束 ===")
}