📚 原创系列: “Go语言学习系列”
🔄 转载说明: 本文最初发布于"Gopher部落"微信公众号,经原作者授权转载。
🔗 关注原创: 欢迎扫描文末二维码,关注"Gopher部落"微信公众号获取第一手Go技术文章。
📑 Go语言学习系列导航
🚀 第三阶段:进阶篇本文是【Go语言学习系列】的第28篇,当前位于第三阶段(进阶篇)
- 并发编程(一):goroutine基础👈 当前位置
- 并发编程(二):channel基础
- 并发编程(三):select语句
- 并发编程(四):sync包
- 并发编程(五):并发模式
- 并发编程(六):原子操作与内存模型
- 数据库编程(一):SQL接口
- 数据库编程(二):ORM技术
- Web开发(一):路由与中间件
- Web开发(二):模板与静态资源
- Web开发(三):API开发
- Web开发(四):认证与授权
- Web开发(五):WebSocket
- 微服务(一):基础概念
- 微服务(二):gRPC入门
- 日志与监控
- 第三阶段项目实战:微服务聊天应用
📖 文章导读
在本文中,您将了解:
- goroutine的概念及其与传统线程的核心区别
- Go运行时如何管理和调度goroutine
- 如何正确创建和使用goroutine
- CSP并发模型的基本思想与应用
- 避免goroutine泄漏和竞态条件的最佳实践
- 在实际项目中应用goroutine的常见模式
无论您是并发编程新手还是有经验的开发者,本文都将帮助您掌握Go语言最具特色的并发特性,为编写高效可靠的并发程序奠定基础。

并发编程(一):goroutine基础
并发编程是Go语言最具特色的功能之一,它使得我们能够轻松地编写高效的并发程序。Go语言通过goroutine和channel两大核心机制,为开发者提供了简单而强大的并发编程模型。本文将深入探讨goroutine的基础知识,帮助你掌握Go语言并发编程的基本技能。
一、goroutine概念与特性
goroutine是Go语言并发设计的核心,它是一种轻量级的用户态线程,由Go运行时(runtime)管理。
1.1 goroutine与线程的区别
goroutine与传统线程相比有诸多优势:
-
极低的创建和切换成本
- goroutine的初始栈大小仅有2KB(Go 1.18后为2KB,此前是8KB)
- 而线程的栈通常是MB级别
-
动态栈大小
- goroutine的栈大小可以根据需要动态增长和收缩
- 最大可达1GB(64位系统)
-
高效的调度模型
- Go运行时实现了M:N的调度模型
- 多个goroutine(N)可以在少量系统线程(M)上运行
- 避免了上下文切换的高成本
-
与线程的数量对比
- 系统可以轻松支持数十万甚至数百万的goroutine同时运行
- 创建同等数量的线程会耗尽系统资源
1.2 goroutine的工作原理
Go运行时负责goroutine的创建、调度和销毁:
┌─────────────────────┐
│ Go 应用程序 │
│ ┌───────┬───────┐ │
│ │ goroutine │ │
│ │ goroutine │ │
│ │ ... │ │
│ └───────┴───────┘ │
└──────────┬──────────┘
│
┌──────────▼──────────┐
│ Go 运行时 │
│ ┌───────┬───────┐ │
│ │ 调度器 │ GC │ │
│ └───────┴───────┘ │
└──────────┬──────────┘
│
┌──────────▼──────────┐
│ 操作系统 │
│ ┌───────┬───────┐ │
│ │ 线程 │ 内存 │ │
│ └───────┴───────┘ │
└─────────────────────┘
- GMP模型:Go调度器基于GMP模型工作
- G: goroutine,用户级线程
- M: machine,操作系统线程
- P: processor,调度上下文,负责连接M和G
二、启动与调度
在Go中启动goroutine非常简单,只需使用go关键字即可。
2.1 创建goroutine
package main
import (
"fmt"
"time"
)
func sayHello() {
fmt.Println("Hello from goroutine!")
}
func main() {
// 启动一个goroutine
go sayHello()
// 防止主goroutine退出太快
time.Sleep(100 * time.Millisecond)
fmt.Println("Main function finished")
}
在这个例子中:
go sayHello()启动了一个新的goroutine执行sayHello函数- 主函数不会等待goroutine完成,需要通过
time.Sleep让主goroutine等待
2.2 传递参数
启动goroutine时可以传递参数:
func printValue(val int) {
fmt.Printf("Value: %d\n", val)
}
func main() {
for i := 0; i < 5; i++ {
// 通过函数参数传值
go printValue(i)
}
time.Sleep(100 * time.Millis

最低0.47元/天 解锁文章

被折叠的 条评论
为什么被折叠?



