# Golang 并发编程最佳实践 **Published by:** [Robin](https://paragraph.com/@robin-8/) **Published on:** 2023-03-02 **URL:** https://paragraph.com/@robin-8/golang-7 ## Content sync.WaitGroupvar wg sync.WaitGroup func f1(i int) { defer wg.Done() time.Sleep(time.Second * time.Duration(rand.Intn(5))) fmt.Println(i) } func main() { for i := 0; i < 10; i++ { wg.Add(1) go f1(i) } wg.Wait() } channelvar wg sync.WaitGroup // 1. 启动一个goroutin 生成100个数发送到ch1 func f1(ch1 chan int) { defer wg.Done() for i := 0; i < 100; i++ { ch1 <- i } close(ch1) } // 2. 启用一个routine,从ch1中取值,计算平方放到ch2 func f2(ch1, ch2 chan int) { defer wg.Done() for { x, ok := <-ch1 if !ok { break } ch2 <- x * x } close(ch2) } // 3. 在main中从ch2取值打印出来 func main() { a := make(chan int, 50) b := make(chan int, 100) wg.Add(2) go f1(a) go f2(a, b) wg.Wait() for ret := range b { fmt.Println(ret) } } 线程池 goroutin-poolvar wg sync.WaitGroup func worker(id int, jobs <-chan int, results chan<- int) { defer wg.Done() fmt.Printf("worker:%d has started.\n", id) for j := range jobs { fmt.Printf("worker:%d start job:%d\n", id, j) time.Sleep(time.Second * 1) fmt.Printf("worker:%d end job:%d\n", id, j) results <- j * 2 } } func main() { jobs := make(chan int, 100) results := make(chan int, 100) // 启动10个线程worker处理数据 for w := 1; w <= 10; w++ { wg.Add(1) go worker(w, jobs, results) } time.Sleep(time.Second * 3) fmt.Println("All of workers have already started.") // 后台生成100个job任务 go func() { for j := 1; j <= 100; j++ { jobs <- j } close(jobs) }() wg.Wait() fmt.Println("Finished all jobs.") } 典型使用场景// 使用goroutin和channel实现一个计算int64随机数各位和的程序 // 1. 开启一个goroutin循环生成int64类型随机数,发送到jobChan // 2. 开启24个goroutin从jobChan中取出随机数计算各位的和,将结果发送到resultChan // 3. 主goroutine从resultChan中取出来结果并打印到终端 var wg sync.WaitGroup type job struct { value int64 } type result struct { job *job sum int64 } var jobChan = make(chan *job, 100) var resultChan = make(chan *result, 100) func producer(jobs chan<- *job) { defer wg.Done() // 循环生成int64类型随机数,发送到jobChan for { x := rand.Int63() newJob := &job{ value: x, } jobs <- newJob time.Sleep(time.Millisecond * 500) } } func consumer(jobs <-chan *job, r chan<- *result) { defer wg.Done() // 从jobChan中取出随机数计算各位的和,将结果发送到resultChan for { job := <-jobs sum := int64(0) n := job.value for n > 0 { sum += n % 10 n = n / 10 } newResult := &result{ job: job, sum: sum, } resultChan <- newResult } } func main() { wg.Add(1) go producer(jobChan) wg.Add(24) for i := 0; i < 24; i++ { go consumer(jobChan, resultChan) } for result := range resultChan { fmt.Printf("value:%d sum:%d\n", result.job.value, result.sum) } wg.Wait() } ## Publication Information - [Robin](https://paragraph.com/@robin-8/): Publication homepage - [All Posts](https://paragraph.com/@robin-8/): More posts from this publication - [RSS Feed](https://api.paragraph.com/blogs/rss/@robin-8): Subscribe to updates