Go语言设计模式:面向专业开发人员的高级进阶
\n\nGo(Golang)是一种专为高效处理并发和微服务架构而设计的语言。诸如单例(Singleton)或工厂(Factory)等基础设计模式广为人知,但要构建高负载、高容错的系统,需要掌握高级设计模式。本文将深入剖析四个关键模式:Fan-Out/Fan-In、Pipeline、Worker Pool和Circuit Breaker。每个模式都能解决扩展、并行处理以及防止系统级联故障等实际问题。
\n\n1. Fan-Out / Fan-In 模式:并行数据处理
\n\n该模式是Go语言并行计算的基础。Fan-Out(扇出)将负载分发到多个goroutine,而Fan-In(扇入)则将结果汇总回一个通道。
\n\nFan-Out 实现
\n假设有一个任务:需要处理100个URL。我们不是顺序处理,而是启动10个goroutine,每个goroutine从共享通道中获取任务。
\n\npackage main\n\nimport (\n "fmt"\n "sync"\n)\n\nfunc worker(id int, jobs <-chan int, results chan<- int, wg *sync.WaitGroup) {\n defer wg.Done()\n for job := range jobs {\n // 模拟处理\n results <- job * 2\n fmt.Printf("Worker %d processed job %d\\n", id, job)\n }\n}\n\nfunc main() {\n const numJobs = 20\n const numWorkers = 5\n\n jobs := make(chan int, numJobs)\n results := make(chan int, numJobs)\n var wg sync.WaitGroup\n\n // Fan-Out:启动工作者\n for w := 1; w <= numWorkers; w++ {\n wg.Add(1)\n go worker(w, jobs, results, &wg)\n }\n\n // 发送任务\n for j := 1; j <= numJobs; j++ {\n jobs <- j\n }\n close(jobs)\n\n // Fan-In:等待完成并关闭results\n go func() {\n wg.Wait()\n close(results)\n }()\n\n // 收集结果\n for result := range results {\n fmt.Println("Result:", result)\n }\n}\n\n\n关键点:
\n- \n
jobs通道作为Fan-Out点:所有工作者从中读取。 \n results通道作为Fan-In点:所有工作者向其中写入。 \n - 使用
sync.WaitGroup确保在所有goroutine完成后才关闭results。 \n
2. Pipeline 模式:流水线数据处理
\n\nPipeline是一个阶段链,每个阶段处理数据并将其传递给下一个阶段。在Go中,这通过一系列通道实现。该模式非常适合ETL流程、日志处理或数据转换。
\n\n示例:文本处理流水线
\n\npackage main\n\nimport "fmt"\n\n// 阶段1:生成数字\nfunc generate(nums ...int) <-chan int {\n out := make(chan int)\n go func() {\n for _, n := range nums {\n out <- n\n }\n close(out)\n }()\n return out\n}\n\n// 阶段2:计算平方\nfunc square(in <-chan int) <-chan int {\n out := make(chan int)\n go func() {\n for n := range in {\n out <- n * n\n }\n close(out)\n }()\n return out\n}\n\n// 阶段3:乘以2\nfunc multiply(in <-chan int, factor int) <-chan int {\n out := make(chan int)\n go func() {\n for n := range in {\n out <- n * factor\n }\n close(out)\n }()\n return out\n}\n\nfunc main() {\n // 组装流水线\n pipeline := multiply(square(generate(1, 2, 3, 4)), 10)\n\n // 消费结果\n for result := range pipeline {\n fmt.Println(result) // 10, 40, 90, 160\n }\n}\n\n\n优势:
\n- \n
- 每个阶段都是独立的