main.go
· 1.2 KiB · Go
Eredeti
package main
import (
"fmt"
"log"
"math/rand"
"sync"
"github.com/hashicorp/go-multierror"
)
func main() {
if err := runConcurrently(); err != nil {
log.Fatalf("errors occured: %v", err)
}
log.Printf("all done, no errors")
}
func runConcurrently() error {
intChan := make(chan int)
wg := sync.WaitGroup{}
workers := 5
errC := make(chan error)
// producer
wg.Add(1)
go func() {
defer wg.Done()
defer close(intChan)
// insert random numbers into the channel
for i := 0; i < 30; i++ {
intChan <- rand.Intn(100)
}
}()
// consumer
for i := 0; i < workers; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for {
select {
case number, ok := <-intChan:
if !ok {
return
}
if err := doSomething(number); err != nil {
errC <- err
}
}
}
}()
}
go func() {
wg.Wait()
close(errC)
}()
var errs *multierror.Error
for {
select {
case err, ok := <-errC:
if !ok {
return errs.ErrorOrNil()
}
if err != nil {
errs = multierror.Append(errs, err)
}
}
}
}
func doSomething(i int) error {
if i%15 == 0 {
return fmt.Errorf("random error: %v", i)
}
log.Printf("doing something with %d", i)
return nil
}
| 1 | package main |
| 2 | |
| 3 | import ( |
| 4 | "fmt" |
| 5 | "log" |
| 6 | "math/rand" |
| 7 | "sync" |
| 8 | |
| 9 | "github.com/hashicorp/go-multierror" |
| 10 | ) |
| 11 | |
| 12 | func main() { |
| 13 | if err := runConcurrently(); err != nil { |
| 14 | log.Fatalf("errors occured: %v", err) |
| 15 | } |
| 16 | log.Printf("all done, no errors") |
| 17 | } |
| 18 | |
| 19 | func runConcurrently() error { |
| 20 | intChan := make(chan int) |
| 21 | wg := sync.WaitGroup{} |
| 22 | workers := 5 |
| 23 | errC := make(chan error) |
| 24 | |
| 25 | // producer |
| 26 | wg.Add(1) |
| 27 | go func() { |
| 28 | defer wg.Done() |
| 29 | defer close(intChan) |
| 30 | // insert random numbers into the channel |
| 31 | for i := 0; i < 30; i++ { |
| 32 | intChan <- rand.Intn(100) |
| 33 | } |
| 34 | }() |
| 35 | |
| 36 | // consumer |
| 37 | for i := 0; i < workers; i++ { |
| 38 | wg.Add(1) |
| 39 | go func() { |
| 40 | defer wg.Done() |
| 41 | for { |
| 42 | select { |
| 43 | case number, ok := <-intChan: |
| 44 | if !ok { |
| 45 | return |
| 46 | } |
| 47 | if err := doSomething(number); err != nil { |
| 48 | errC <- err |
| 49 | } |
| 50 | } |
| 51 | } |
| 52 | }() |
| 53 | } |
| 54 | |
| 55 | go func() { |
| 56 | wg.Wait() |
| 57 | close(errC) |
| 58 | }() |
| 59 | |
| 60 | var errs *multierror.Error |
| 61 | |
| 62 | for { |
| 63 | select { |
| 64 | case err, ok := <-errC: |
| 65 | if !ok { |
| 66 | return errs.ErrorOrNil() |
| 67 | } |
| 68 | if err != nil { |
| 69 | errs = multierror.Append(errs, err) |
| 70 | } |
| 71 | } |
| 72 | } |
| 73 | } |
| 74 | |
| 75 | func doSomething(i int) error { |
| 76 | if i%15 == 0 { |
| 77 | return fmt.Errorf("random error: %v", i) |
| 78 | } |
| 79 | log.Printf("doing something with %d", i) |
| 80 | return nil |
| 81 | } |
| 82 |