2026-01-07 17:46:57
Golang并发基础与goroutine使用方法
Go语言通过goroutine和channel构建了简单高效的并发模型,其核心优势在于轻量级并发执行与安全通信机制。掌握goroutine的启动、同步控制及数据交换方式,是编写高性能并发程序的关键。
一、Goroutine基础定义:Goroutine是Go运行时管理的轻量级线程,由Go runtime调度,具有极小的内存开销(初始栈空间通常为2KB,可动态扩展)。与操作系统线程相比,可轻松创建数万个goroutine而不影响性能。
启动方式:在函数调用前添加go关键字即可启动一个goroutine。
func sayHello() { fmt.Println("Hello from goroutine")}func main() { go sayHello() // 启动goroutine time.Sleep(100 * time.Millisecond) // 简单等待(实际开发中不推荐) fmt.Println("Main function")}注意:直接使用time.Sleep等待goroutine完成仅适用于演示,实际开发需通过同步机制控制生命周期。
二、Goroutine同步控制:sync.WaitGroup作用:协调多个goroutine的执行,确保主函数等待所有任务完成后再退出。
核心方法:
示例:
func worker(id int, wg *sync.WaitGroup) { defer wg.Done() // 任务完成时减少计数器 fmt.Printf("Worker %d startingn", id) time.Sleep(time.Second) fmt.Printf("Worker %d donen", id)}func main() { var wg sync.WaitGroup for i := 1; i <= 3; i++ { wg.Add(1) // 每个goroutine启动前增加计数器 go worker(i, &wg) } wg.Wait() // 阻塞直到所有worker完成 fmt.Println("All workers finished")}关键点:
设计原则:Go提倡“不要通过共享内存来通信,而应该通过通信来共享内存”。Channel是goroutine间安全交换数据的管道。
基本操作:
无缓冲通道(同步通信):发送与接收操作会阻塞,直到另一端准备好。
func fetchData(ch chan string) { time.Sleep(2 * time.Second) ch <- "data fetched" // 阻塞直到数据被接收}func main() { ch := make(chan string) go fetchData(ch) result := <-ch // 阻塞直到数据到达 fmt.Println(result)}有缓冲通道(异步通信):通道可存储固定数量的数据,发送或接收操作仅在缓冲区满/空时阻塞。
func main() { ch := make(chan int, 2) // 缓冲区大小为2 ch <- 1 ch <- 2 fmt.Println(<-ch) // 输出1 fmt.Println(<-ch) // 输出2}四、并发编程最佳实践完整示例:并发请求与结果汇总
func fetchURL(url string, ch chan<- string) { resp, err := http.Get(url) if err != nil { ch <- fmt.Sprintf("error fetching %s: %v", url, err) return } defer resp.Body.Close() ch <- fmt.Sprintf("success: %s", url)}func main() { urls := []string{"通过掌握goroutine的启动、sync.WaitGroup的同步控制及channel的通信机制,可高效实现Go语言的并发编程。实际开发中需结合场景选择合适的同步与通信方式,确保程序的正确性与性能。