概述
Go 语言的强大之处在于其内置的并发支持,而 goroutine 是其并发编程的核心。
本文将讨论如何高效使用 goroutine,通过清晰的示例代码和注释,帮助读者更好地理解和应用并发编程。
1. 了解 goroutine 的基础
g
package main import ( "fmt" "time") func main() { // 创建并启动goroutine go func() { for i := 0; i < 5; i++ { fmt.Println("Goroutine:", i) time.Sleep(time.Second) } }() // 主goroutine for i := 0; i < 3; i++ { fmt.Println("Main:", i) time.Sleep(time.Second) }}
2. goroutine 之间的通信
用通道进行通信
package main import ( "fmt" "sync" "time") func main() { var wg sync.WaitGroup ch := make(chan int) // 启动goroutine发送数据 wg.Add(1) go func() { defer wg.Done() for i := 0; i < 5; i++ { ch <- i time.Sleep(time.Second) } close(ch) }() // 启动goroutine接收数据 wg.Add(1) go func() { defer wg.Done() for num := range ch { fmt.Println("Received:", num) } }() // 等待所有goroutine执行完毕 wg.Wait()}
3. 避免 goroutine 泄漏
使
package main import ( "fmt" "sync") func main() { var wg sync.WaitGroup // 创建带缓冲的通道 ch := make(chan int, 3) // 启动goroutine发送数据 wg.Add(1) go func() { defer wg.Done() for i := 0; i < 5; i++ { ch <- i } close(ch) }() // 启动goroutine接收数据 wg.Add(1) go func() { defer wg.Done() for num := range ch { fmt.Println("Received:", num) } }() // 等待所有goroutine执行完毕 wg.Wait()}
4. 控制 goroutine 的数量
使
package main import ( "fmt" "sync" "time") func worker(id int, jobs <-chan int, results chan<- int) { for j := range jobs { fmt.Println("Worker", id, "processing job", j) time.Sleep(time.Second) results <- j * 2 }} func main() { const numJobs = 5 const numWorkers = 3 jobs := make(chan int, numJobs) results := make(chan int, numJobs) // 启动goroutine池 var wg sync.WaitGroup for w := 1; w <= numWorkers; w++ { wg.Add(1) go func(workerID int) { defer wg.Done() worker(workerID, jobs, results) }(w) } // 提供工作 for j := 1; j <= numJobs; j++ { jobs <- j } close(jobs) // 收集结果 go func() { wg.Wait() close(results) }() // 输出结果 for res := range results { fmt.Println("Result:", res) }}
5. 使用 sync 包进行同步
package main import ( "fmt" "sync" "time") func main() { var wg sync.WaitGroup // 启动多个goroutine for i := 1; i <= 3; i++ { wg.Add(1) go func(id int) { defer wg.Done() time.Sleep(time.Second) fmt.Println("Goroutine", id, "completed") }(i) } // 等待所有goroutine执行完毕 wg.Wait() fmt.Println("All goroutines completed")}
6. 性能调优和注意事项
避
package main import ( "fmt" "sync" "time") func main() { var mu sync.Mutex counter := 0 for i := 0; i < 5; i++ { go func() { mu.Lock() defer mu.Unlock() counter++ }() } time.Sleep(time.Second) fmt.Println("Counter:", counter)}
7. 总结
通过本文的例子和讨论,对如何高效使用 goroutine 有了更深入的理解。
理解 goroutine 的创建、通信、避免泄漏、控制数量、同步等方面的技巧,将有助于读者在实际项目中更好地应用 Go 语言的并发编程特性。
并发不仅是 Go 语言的一项强大功能,更是构建高性能应用的关键。