全部学科
NodeJS全栈
nodejs
Python全栈
python
小程序首页
📅 2026-05-13 6 分钟 ✍️ juanwangdev

Go goroutine基本概念与创建

Goroutine是Go并发编程的基础,轻量高效。

什么是Goroutine

定义

Goroutine是Go运行时管理的轻量级线程,由Go调度器调度执行。

Go
// 创建goroutine
go func() {
    fmt.Println("Hello from goroutine")
}()

特性

特性GoroutineOS线程
初始栈大小2KB1-8MB
最大栈限制1GB固定
创建开销极低较高
切换开销
数量限制百万级数千

创建Goroutine

go关键字

Go
// 函数形式
go myFunction()

// 匿名函数
go func() {
    fmt.Println("匿名函数")
}()

// 匿名函数传参
go func(name string) {
    fmt.Println("Hello", name)
}("Tom")

立即执行

Go
func main() {
    go fmt.Println("并发")  // 立即启动

    fmt.Println("主线程")  // 可能先或后输出

    time.Sleep(100 * time.Millisecond)  // 等待goroutine
}

go语句立即返回,不等待goroutine完成。

Goroutine生命周期

创建到结束

Go
go func() {
    // 1. 创建:状态Runnable
    // 2. 调度执行:状态Running
    // 3. 执行完毕:状态Dead
}()

等待完成

Go
// 使用WaitGroup等待
var wg sync.WaitGroup

wg.Add(1)
go func() {
    defer wg.Done()
    fmt.Println("工作")
}()

wg.Wait()  // 等待完成

Goroutine与主程序

主程序退出时goroutine终止

Go
func main() {
    go func() {
        time.Sleep(1 * time.Second)
        fmt.Println("可能不打印")  // main已退出
    }()

    // main立即退出,goroutine被终止
}

必须等待

Go
func main() {
    var wg sync.WaitGroup

    wg.Add(1)
    go func() {
        defer wg.Done()
        time.Sleep(1 * time.Second)
        fmt.Println("会打印")
    }()

    wg.Wait()  // 等待goroutine
}

Goroutine栈增长

动态扩容

Go
// 栈从2KB开始
// 函数调用深度增加时自动扩容

func deep(n int) {
    if n <= 0 {
        return
    }
    var buf [1024]byte  // 使用栈空间
    deep(n - 1)         // 可能触发扩容
}

go deep(10000)  // 栈可能增长到数MB

栈收缩

Go
// GC时检查栈使用率
// 使用率低时自动收缩
// 最终回到最小2KB

Goroutine数量

获取数量

Go
// 返回当前存在的goroutine数
n := runtime.NumGoroutine()
fmt.Println("Goroutine数量:", n)

大量goroutine

Go
// Go可以轻松创建百万goroutine
for i := 0; i < 1000000; i++ {
    go func() {
        time.Sleep(1 * time.Second)
    }()
}

// 内存占用约2GB(2KB × 100万)
// 比百万OS线程(1MB × 100万 = 1TB)高效得多

常见陷阱

闭包捕获变量

Go
// 错误:所有goroutine打印相同值
for i := 0; i < 10; i++ {
    go func() {
        fmt.Println(i)  // 可能全打印10
    }()
}

// 正确:传递参数
for i := 0; i < 10; i++ {
    go func(n int) {
        fmt.Println(n)  // 打印0-9
    }(i)
}

goroutine泄漏

Go
// 错误:goroutine永久阻塞
func leak() {
    ch := make(chan int)
    go func() {
        <-ch  // 永久等待,goroutine泄漏
    }()
    // ch从未发送数据
}

// 正确:确保goroutine能退出
func noLeak() {
    ch := make(chan int, 1)
    go func() {
        v, ok := <-ch
        if !ok {
            return  // channel关闭时退出
        }
    }()
    ch <- 1
    close(ch)
}

Goroutine vs Thread

对比项GoroutineThread
内存开销2KB起1MB起
创建耗时微秒毫秒
切换耗时纳秒微秒
调度方式Go调度器OS调度
最大数量百万数千
栈伸缩动态固定

要点总结

  • Goroutine是轻量级线程,由Go调度器管理
  • 初始栈2KB,可动态增长到1GB
  • go关键字立即启动goroutine
  • 主程序退出时goroutine终止
  • 用WaitGroup等待goroutine完成
  • 闭包捕获变量是常见陷阱
  • 避免goroutine泄漏
  • 可轻松创建百万goroutine
  • 比OS线程高效得多

📝 发现内容有误?点击此处直接编辑

← 上一篇 Go channel类型与通信详解
下一篇 → Go常见并发模式详解
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库