- Goroutine 秀才 2025年2月14日 大约 5 分钟 Go语言 Go语言 golang go进阶语法 Goroutine 此页内容 1. Goroutine使用 2. 主协程 3. 多协程调用 goroutine 是Go语言对于协程的支持,可以把它理解为Go语言的协程。这是一个Go语言并发编程的终极杀器,它让我们的并发编程变得简单。 Go语言的并发只会用到 goroutine ,并不需要我们去考虑用多进程或者是多线程。有过C++或者Java经验的同学可能知道,线程本身是有一定大小的,一般OS线程栈大小为2MB,且线程在创建和上下文切换的时候是需要消耗资源的,会带来性能损耗,所以在我们用到多线程技术的时候,我们往往会通过池化技术,即创建线程池来管理一定数量的线程。 在Go语言中,一个 goroutine 栈在其生命周期开始时占用空间很小(一般2KB),并且栈大小可以按需增大和缩小, goroutine 的栈大小限制可以达到1GB,但是一般不会用到这么大。所以在Go语言中一次创建成千上万,甚至十万左右的 goroutine 理论上也是可以的。 在Go语言中,我们用多 goroutine 来完成并发,在某个任务需要并发执行的时候,只需要把这个任务包装成一个函数,开启一个 goroutine 去执行这个函数就可以了。并不需要我们来维护一个类似于线程池的东西,也不需要我们去关心协程是怎么切换和调度的,因为这些都已经有Go语言内置的调度器帮我们做了,并且效率还非常高。 1. Goroutine使用 goroutine 使用起来非常方便,通常我们会将需要并发的任务封装成一个函数,然后再该函数前加上 go 关键字就行了,这样就开启了一个 goroutine 。
func()
go func() // 会并发执行这个函数
- 主协程 和其它语言一样,Go程序的入口也是 main 函数。在程序开始执行的时候,Go程序会为 main 函数创建一个默认的 goroutine ,我们称之为主协程,我们后来人为的创建的一些 goroutine ,都是在这个主 goroutine 的基础上进行的。 下面请看个例子:
package main
import "fmt"
func myGroutine() {
fmt.Println("myGroutine")
}
func main() {
go myGroutine()
fmt.Println("end!!!")
}
运行结果:
end!!!
myGroutine
很奇怪,明明是多协程任务,为什么只打印了主协程里的"end!!!",而没有打印我们开启的协程里的输出"myGroutine",按理不是应该都打印出来吗? 这是因为:当 main 函数返回的时候该 goroutine 就结束了,当主协程退出的时候,其他剩余的 goroutine 不管是否运行完,都会跟着结束。所以,这里主协程打印完"end!!!"之后就退出了, myGroutine 协程可能还没运行到 fmt.Println("myGroutine") 语句也跟着退出了。 接下来我们让主 goroutine 执行完 fmt.Println("end!!!") 之后不立刻退出,而是等待2s,看一下运行结果:
package main
import (
"fmt"
"time"
)
func myGroutine() {
fmt.Println("myGroutine")
}
func main() {
go myGroutine()
fmt.Println("end!!!")
time.Sleep(2*time.Second)
}
运行结果:
end!!!
myGroutine
此时打印出了我们想要的结果,这里我们通过让主协程睡眠2s来等待子协程执行完了之后再退出,后面我们会学习到更好的方法,这里就不再过多阐述。 3. 多协程调用 在Go语言中,我们可以通过 go 关键字来开启多个协程,每个协程可以并发执行,互不干扰。
package main
import (
"fmt"
"sync"
"time"
)
func myGoroutine(name string, wg *sync.WaitGroup) {
defer wg.Done()
for i := 0; i < 5; i++ {
fmt.Printf("myGroutine %s\n", name)
time.Sleep(10 * time.Millisecond)
}
}
func main() {
var wg sync.WaitGroup
wg.Add(2)
go myGoroutine("goroutine1", &wg)
go myGoroutine("goroutine2", &wg)
wg.Wait()
}
运行结果:
myGroutine goroutine1
myGroutine goroutine2
从结果中可以看到,两个协程并发执行,互不干扰。注意在上述例子中,我们使用了 sync.WaitGroup 来等待所有协程执行完毕之后再退出。关于 sync.WaitGroup 的详细介绍,可以参考 sync.WaitGroup 。后续也会在 sync 章节详细介绍。 关注秀才公众号: IT杨秀才 ,领取精品学习资料 公众号后台回复: Go面试 ,领取Go面试题库PDF 公众号后台回复: Go学习 ,领取Go必看书籍 公众号后台回复: 大模型 ,领取大模型学习资料 公众号后台回复: 111 ,领取架构学习资料 公众号后台回复: 26届秋招 ,领取26届秋招企业汇总表
🔥 配套实战项目,拆得开、跑得起、能写进简历 多 Agent 编排 + RAG 混合检索 · 31 篇深度教程 + 50+ 面试题 点击查看 DevSupport AI 实战项目 → 在 GitHub 上编辑此页 上次编辑于: 2026/6/24 23:41:22 贡献者: Percygu , Your Name , gupeng 上一页 1. 并发概述 下一页 3. Channel