Goroutine基础
Goroutine是Go语言并发编程的核心,本文档介绍Goroutine的基本概念、特性和使用方法。
📋 目录
什么是Goroutine
Goroutine是Go语言中的轻量级线程,是Go并发编程的基础单元。它可以与其他函数或方法并发执行,实现真正的并行处理。
核心特点
- 轻量级:创建成本极低,可以轻松创建成千上万个Goroutine
- 并发执行:多个Goroutine可以同时运行
- 自动调度:由Go运行时自动管理和调度
Goroutine的优势
与传统线程对比
| 特性 | Goroutine | 传统线程 |
|---|---|---|
| 内存开销 | 2KB起始栈 | 2MB固定栈 |
| 创建成本 | 极低 | 较高 |
| 切换成本 | 纳秒级 | 微秒级 |
| 数量限制 | 数十万个 | 数千个 |
| 调度方式 | 协作式调度 | 抢占式调度 |
技术优势
动态栈管理
- 初始栈大小仅2KB
- 根据需要自动扩展和收缩
- 避免栈溢出问题
M:N调度模型
- 多个Goroutine映射到少数OS线程
- 智能负载均衡
- 自动处理阻塞操作
内置通信机制
- 通过Channel进行安全通信
- 避免共享内存竞争
- 遵循"不要通过共享内存来通信,而要通过通信来共享内存"
创建Goroutine
基本语法
在函数调用前加上go关键字即可创建Goroutine:
go functionName() // 创建新的Goroutine执行函数第一个Goroutine示例
package main
import (
"fmt"
"time"
)
func hello() {
fmt.Println("Hello from Goroutine!")
}
func main() {
go hello() // 创建新的Goroutine
fmt.Println("Hello from main!")
// 等待Goroutine执行完成
time.Sleep(1 * time.Second)
}输出结果:
Hello from main!
Hello from Goroutine!Goroutine的特性
1. 非阻塞执行
Goroutine的创建是非阻塞的,程序不会等待Goroutine执行完成:
func main() {
go hello() // 立即返回,不等待hello()执行完成
fmt.Println("main function") // 立即执行
// 程序可能在hello()执行前就结束了
}
fmt.Println("main function")
}上面的程序中,第13行,我们调用 time 包的 Sleep 函数来使调用该函数所在的协程休眠。在这里是让主协程休眠1秒钟。现在调用 go hello() 有了足够的时间得以在主协程退出之前执行。该程序首先打印 Hello world goroutine,等待1秒钟之后打印 main function。
在主协程中使用 Sleep 函数等待其他协程结束的方法是不正规的,我们用在这里只是为了说明Go协程是如何工作的。信道可以用于阻塞主协程,直到其他协程执行完毕。我们将在下一篇教程中讨论信道。
开启多个协程
让我们写一个程序开启多个协程来更好的理解协程。
package main
import (
"fmt"
"time"
)
func numbers() {
for i := 1; i <= 5; i++ {
time.Sleep(250 * time.Millisecond)
fmt.Printf("%d ", i)
}
}
func alphabets() {
for i := 'a'; i <= 'e'; i++ {
time.Sleep(400 * time.Millisecond)
fmt.Printf("%c ", i)
}
}
func main() {
go numbers()
go alphabets()
time.Sleep(3000 * time.Millisecond)
fmt.Println("main terminated")
}上面的程序在第21和22行开启了两个协程。现在这两个协程同时执行。numbers 协程最初睡眠 250 毫秒,然后打印 1,接着再次睡眠然后打印2,以此类推,直到打印到 5。类似地,alphabets 协程打印从 a 到 e 的字母,每个字母之间相隔 400 毫秒。主协程开启 numbers 和 alphabets 协程,等待 3000 毫秒,最后终止。
程序的输出为:
1 a 2 3 b 4 c 5 d e main terminated
下面的图片描述了这个程序是如何工作的,请在新的标签中打开图像以获得更好的效果:

上图中,蓝色的线框表示 numbers 协程,栗色的线框表示 alphabets 协程。绿色的线框表示主协程。黑色的线框合并了上述三个协程,向我们展示了该程序的工作原理。每个框顶部的 0ms,250 ms 的字符串表示以毫秒为单位的时间,在每个框底部的 1,2,3 表示输出。
蓝色的线框告诉我们在 250ms 的时候打印了1,在 500ms 的时候打印了2,以此类推。因此最后一个线框底部的输出:1 a 2 3 b 4 c 5 d e main terminated 也是整个程序的输出。上面的图像是很好理解的,您将能够了解该程序的工作原理。