Go 语言在设计时就将并发作为语言的一大特性。Go 代码跑在一个个 goroutine 中。
Goroutine 事实上是协程(coroutine)换了个马甲。相对于线程:
- Goroutine 比线程轻量(在栈上只需要几 kB),在用户态做切换,并且栈大小可以伸展和收缩,而线程往往需要指定固定的大小
- Goroutine 所需要的线程数非常少。一个线程可能跑几千个 goroutine。当一个 goroutine 被 I/O block 时,Go 有可能为其他 goroutine 的运行创建新的线程,但开发都不需要关心这些细节,Go 做了屏蔽
- Goroutine 之间的通讯用了 channel,channel 的机制从设计上避免了 race condition,使得开发起来很便利
基础例子
package main
import (
"fmt"
"time"
)
func hello() {
fmt.Println("Hello world goroutine")
}
func main() {
// 启动一个独立运行的 goroutine
go hello()
// 如果没有这行,hello() 可能不会被执行,因为 main 函数一旦结束,
// 整个程序就退出了
time.Sleep(1 * time.Second)
fmt.Println("main function")
}
Hello world goroutine
main function