langShift

并发和 Goroutine

Go 的并发模型是其最显著的特性之一,围绕 goroutine 和 channel 的概念构建。与 JavaScript 的单线程事件循环或 C++ 的复杂线程模型不同,Go 提供了一种简单而强大的并发编程方法,其座右铭是"不要通过共享内存来通信;要通过通信来共享内存"。

并发 vs 并行

并发是通过交错执行来处理多个任务的能力,而并行是在不同 CPU 核心上同时执行多个任务的能力。

  • JavaScript: 主要通过事件循环实现并发,通过 Web Workers 实现有限的并行
  • Go: 既支持并发(goroutine)也支持并行(可以利用多个 CPU 核心)

Goroutine: 轻量级线程

Goroutine 是 Go 处理并发操作的方式。它们是由 Go 运行时管理的轻量级线程,而不是操作系统。

正在加载...

Goroutine 生命周期

创建 Goroutine

Goroutine 使用 go 关键字后跟函数调用来创建:

正在加载...

Goroutine 同步

与 JavaScript 基于 Promise 的同步不同,Go 使用 channel 和同步原语:

正在加载...

Channel: Goroutine 间的通信

Channel 是 Go 中 goroutine 间通信的主要机制。它们提供了一种安全的数据共享方式,无需显式锁定。

基本 Channel 操作

正在加载...

缓冲 vs 无缓冲 Channel

正在加载...

Select 语句

select 语句允许 goroutine 等待多个 channel 操作:

正在加载...

常见并发模式

工作池模式

正在加载...

管道模式

正在加载...

Goroutine 最佳实践

1. 始终处理 Goroutine 生命周期

正在加载...

2. 避免 Goroutine 泄漏

正在加载...

性能考虑

Goroutine vs 线程对比

方面Goroutine操作系统线程
内存~2KB 栈~1MB 栈
创建~0.3μs~17μs
上下文切换~0.2μs~1.7μs
并发数百万级千级

何时使用 Goroutine

  • I/O 密集型操作: 网络请求、文件操作
  • CPU 密集型操作: 数学计算(需要适当协调)
  • 事件处理: 并发处理多个事件
  • 后台任务: 清理、监控、日志记录

练习题:

  1. Go 中并发和并行有什么区别?
  2. Goroutine 在资源使用方面与操作系统线程有何不同?
  3. 解释缓冲 channel 和无缓冲 channel 的区别。
  4. 什么时候使用 select 语句而不是简单的 channel 接收?
  5. 防止 goroutine 泄漏有哪些常见模式?

项目想法:

创建一个使用 goroutine 并发获取多个 URL 的网络爬虫,包含适当的错误处理和速率限制。爬虫应该使用 channel 来协调工作线程并收集结果。