Go语言-->Goroutine 详细解释

Goroutine 详细解释

goroutine 是 Go 语言中的轻量级线程,由 Go 运行时管理。它是实现并发编程的核心机制。

核心概念

特性 说明
轻量级 创建成本极低,一个程序可以轻松创建数百万个 goroutine
并发执行 多个 goroutine 可以同时运行
由运行时管理 Go 运行时自动调度 goroutine 到 CPU 核心上
非抢占式 goroutine 只在特定点(如 I/O、channel 操作)让出控制权

基本用法

1. 创建 Goroutine

go 复制代码
package main

import (
	"fmt"
	"time"
)

func main() {
	// 普通函数调用(同步)
	sayHello("Alice")
	
	// 启动 goroutine(异步)
	go sayHello("Bob")
	
	// 主 goroutine 需要等待子 goroutine 完成
	time.Sleep(1 * time.Second)
}

func sayHello(name string) {
	fmt.Printf("Hello, %s\n", name)
}

输出

复制代码
Hello, Alice
Hello, Bob

2. 多个 Goroutine

go 复制代码
package main

import (
	"fmt"
	"time"
)

func main() {
	for i := 1; i <= 5; i++ {
		go func(id int) {
			fmt.Printf("Goroutine %d 开始\n", id)
			time.Sleep(time.Duration(id) * time.Second)
			fmt.Printf("Goroutine %d 完成\n", id)
		}(i)
	}
	
	// 等待所有 goroutine 完成
	time.Sleep(6 * time.Second)
	fmt.Println("主程序结束")
}

输出

复制代码
Goroutine 1 开始
Goroutine 2 开始
Goroutine 3 开始
Goroutine 4 开始
Goroutine 5 开始
Goroutine 1 完成
Goroutine 2 完成
Goroutine 3 完成
Goroutine 4 完成
Goroutine 5 完成
主程序结束

go func()go sayHello("Bob") 的区别

特性 go func() go sayHello("Bob")
类型 匿名函数 命名函数
定义位置 调用处定义 提前定义
代码量 适合简短逻辑 适合复杂逻辑
可重用性 不可重用 可重用
闭包 可访问外部变量 需要参数传递

Goroutine vs 线程

特性 Goroutine 线程
内存占用 ~2KB ~1-2MB
创建速度 极快 较慢
数量 可创建百万级 通常数百个
切换成本
管理 Go 运行时 操作系统

与 Channel 结合

go 复制代码
package main

import (
	"fmt"
)

func main() {
	// 创建 channel
	results := make(chan string)
	
	// 启动 goroutine
	go func() {
		results <- "任务 1 完成"
	}()
	
	go func() {
		results <- "任务 2 完成"
	}()
	
	// 接收结果
	fmt.Println(<-results)
	fmt.Println(<-results)
}

输出

复制代码
任务 1 完成
任务 2 完成

常见模式

1. 使用 sync.WaitGroup 等待完成

go 复制代码
package main

import (
	"fmt"
	"sync"
)

func main() {
	var wg sync.WaitGroup
	
	for i := 1; i <= 3; i++ {
		wg.Add(1)
		go func(id int) {
			defer wg.Done()
			fmt.Printf("Goroutine %d 执行\n", id)
		}(i)
	}
	
	wg.Wait()
	fmt.Println("所有 goroutine 完成")
}

2. 并发 HTTP 请求

go 复制代码
package main

import (
	"fmt"
	"net/http"
	"sync"
)

func main() {
	urls := []string{
		"https://example.com",
		"https://google.com",
		"https://github.com",
	}
	
	var wg sync.WaitGroup
	for _, url := range urls {
		wg.Add(1)
		go func(u string) {
			defer wg.Done()
			resp, err := http.Get(u)
			if err != nil {
				fmt.Printf("请求 %s 失败: %v\n", u, err)
			} else {
				fmt.Printf("请求 %s 成功,状态码: %d\n", u, resp.StatusCode)
			}
		}(url)
	}
	
	wg.Wait()
}

注意事项

⚠️ 常见问题

  • 主 goroutine 过早退出:子 goroutine 还未完成就结束了
  • 竞态条件:多个 goroutine 同时修改共享变量
  • 死锁:goroutine 互相等待

最佳实践

  • 使用 sync.WaitGroupchannel 等待 goroutine 完成
  • 使用 sync.Mutex 保护共享数据
  • 避免在 goroutine 中直接修改外部变量(使用参数传递)
相关推荐
踏浪无痕21 分钟前
SQLInsight:从JDBC底层到API调用的零侵入SQL监控方案
数据库·后端·开源
智慧地球(AI·Earth)22 分钟前
Codex配置问题解析:wire_api格式不匹配导致的“Reconnecting...”循环
开发语言·人工智能·vscode·codex·claude code
Ralph_Y30 分钟前
C++虚继承
开发语言·c++
杨章隐31 分钟前
Java 解析 CDR 文件并计算图形面积的完整方案(支持 MultipartFile / 网络文件)@杨宁山
java·开发语言
SmartRadio39 分钟前
进一步优化CH585M的低功耗模式
c语言·开发语言·单片机·嵌入式硬件·物联网
Renhao-Wan43 分钟前
Java 并发基石:AQS (AbstractQueuedSynchronizer)
java·开发语言
SweetCode1 小时前
【无标题】
开发语言·c++·算法
shughui1 小时前
Python基础面试题:语言定位+数据类型+核心操作+算法实战(含代码实例)
开发语言·python·算法
No0d1es1 小时前
2025年12月电子学会青少年软件编程Python六级等级考试真题试卷
开发语言·python·青少年编程·等级考试·电子学会
zlp19921 小时前
xxl-job java.sql.SQLException: interrupt问题排查(二)
java·开发语言