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

推荐订阅源

T
Tor Project blog
博客园 - 聂微东
Microsoft Azure Blog
Microsoft Azure Blog
博客园 - 【当耐特】
G
Google Developers Blog
J
Java Code Geeks
The Cloudflare Blog
Attack and Defense Labs
Attack and Defense Labs
宝玉的分享
宝玉的分享
Last Week in AI
Last Week in AI
Cisco Talos Blog
Cisco Talos Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
I
Intezer
Jina AI
Jina AI
T
Tenable Blog
P
Palo Alto Networks Blog
Project Zero
Project Zero
D
DataBreaches.Net
Hugging Face - Blog
Hugging Face - Blog
The Hacker News
The Hacker News
F
Full Disclosure
Cloudbric
Cloudbric
量子位
H
Heimdal Security Blog
K
Kaspersky official blog
有赞技术团队
有赞技术团队
罗磊的独立博客
V
Vulnerabilities – Threatpost
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
阮一峰的网络日志
阮一峰的网络日志
Vercel News
Vercel News
Recent Announcements
Recent Announcements
WordPress大学
WordPress大学
GbyAI
GbyAI
S
SegmentFault 最新的问题
M
MIT News - Artificial intelligence
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
I
InfoQ
Recorded Future
Recorded Future
Security Archives - TechRepublic
Security Archives - TechRepublic
AI
AI
Webroot Blog
Webroot Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
爱范儿
爱范儿
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
T
The Exploit Database - CXSecurity.com
Apple Machine Learning Research
Apple Machine Learning Research
C
Cybersecurity and Infrastructure Security Agency CISA
H
Hacker News: Front Page
Latest news
Latest news

博客园 - 汉克书

新工作新气象 记录一些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=== 示例结束 ===")
}