Go并发编程:goroutine与channel实战
Go语言最令人称道的特性莫过于其原生的并发支持。今天我们来探讨两个核心概念:goroutine和channel,它们共同构成了Go高效的并发模型。
轻量级线程:goroutine
与传统线程相比,goroutine更加轻量,创建成本极低。只需在函数调用前加上go关键字,即可启动一个并发执行单元:
go func() {
fmt.Println("我在并发执行!")
}()
安全的通信:channel
goroutine之间通过channel进行通信,遵循“不要通过共享内存来通信,而要通过通信来共享内存”的理念:
ch := make(chan int, 10) // 创建缓冲大小为10的channel
// 发送数据
ch <- 42
// 接收数据
value := <-ch
实战示例:并发爬虫
下面是一个简单的并发爬虫示例,展示如何协调多个goroutine:
func worker(urls <-chan string, results chan<- string) {
for url := range urls {
// 模拟抓取逻辑
results <- fmt.Sprintf("抓取完成: %s", url)
}
}
func main() {
urls := make(chan string, 100)
results := make(chan string, 100)
// 启动3个worker
for i := 0; i < 3; i++ {
go worker(urls, results)
}
// 发送任务
go func() {
for _, url := range urlList {
urls <- url
}
close(urls)
}()
// 收集结果
for i := 0; i < len(urlList); i++ {
fmt.Println(<-results)
}
}
最佳实践
- 合理设置channel缓冲大小,平衡内存与性能
- 始终确保channel被正确关闭,避免goroutine泄露
- 使用
select语句处理多个channel操作 - 考虑使用
context包实现超时和取消机制
Go的并发模型简洁而强大,正确使用goroutine和channel,可以轻松构建高性能的并发应用,同时保持代码的清晰可维护。这正是Go在云原生时代备受青睐的原因之一。