一. 使用waitgroup控制并发
package main
import (
"fmt"
"math/rand"
"sync"
)
var wg sync.WaitGroup
type randomNum struct {
id int64
number int64
}
type resultNum struct {
randomNum *randomNum
sum int64
}
func producer(ch chan *randomNum) {
var id int64
for i := 0; i < 10000; i++ {
id++
num := rand.Int63()
tmp := &randomNum{
id: id,
number: num,
}
ch <- tmp
}
close(ch)
}
func consumer(ch1 chan *randomNum, ch2 chan *resultNum) {
defer wg.Done()
for v := range ch1 {
sum := calc(v.number)
result := &resultNum{
randomNum: v,
sum: sum,
}
ch2 <- result
}
}
func print(ch chan *resultNum) {
for v := range ch {
fmt.Printf("id:%v randomNum:%v sum:%v\n", v.randomNum.id, v.randomNum.number, v.sum)
}
}
func calc(i int64) int64 {
var sum int64
for i > 0 {
sum += i % 10
i /= 10
}
return sum
}
func nConsumerGoroutine(n int, ch1 chan *randomNum, ch2 chan *resultNum) {
wg.Add(n)
for i := 0; i < n; i++ {
go func(chan *randomNum, chan *resultNum) {
consumer(ch1, ch2)
}(ch1, ch2)
}
}
func main() {
ch1 := make(chan *randomNum, 10000)
ch2 := make(chan *resultNum, 10000)
go func(chan *randomNum) {
producer(ch1)
}(ch1)
nConsumerGoroutine(10, ch1, ch2)
wg.Wait()
close(ch2)
print(ch2)
}
二. 使用空结构体计数控制并发
package main
import (
"fmt"
"math/rand"
)
var doneCh chan struct{}
type randomNum struct {
id int64
number int64
}
type resultNum struct {
randomNum *randomNum
sum int64
}
func producer(ch chan *randomNum) {
var id int64
for i := 0; i < 10000; i++ {
id++
num := rand.Int63()
tmp := &randomNum{
id: id,
number: num,
}
ch <- tmp
}
close(ch)
}
func consumer(ch1 chan *randomNum, ch2 chan *resultNum) {
for v := range ch1 {
sum := calc(v.number)
result := &resultNum{
randomNum: v,
sum: sum,
}
ch2 <- result
}
doneCh <- struct{}{}
}
func print(ch chan *resultNum) {
for v := range ch {
fmt.Printf("id:%v randomNum:%v sum:%v\n", v.randomNum.id, v.randomNum.number, v.sum)
}
}
func calc(i int64) int64 {
var sum int64
for i > 0 {
sum += i % 10
i /= 10
}
return sum
}
func nConsumerGoroutine(n int, ch1 chan *randomNum, ch2 chan *resultNum) {
for i := 0; i < n; i++ {
go func(chan *randomNum, chan *resultNum) {
consumer(ch1, ch2)
}(ch1, ch2)
}
}
func closeCh2(n int, doneCh chan struct{}, ch2 chan *resultNum) {
for i := 0; i < n; i++ {
<-doneCh
}
close(doneCh)
close(ch2)
}
func main() {
ch1 := make(chan *randomNum, 10000)
ch2 := make(chan *resultNum, 10000)
doneCh = make(chan struct{}, 10)
go func(chan *randomNum) {
producer(ch1)
}(ch1)
nConsumerGoroutine(10, ch1, ch2)
closeCh2(10, doneCh, ch2)
print(ch2)
}