DEV Community

Discussion on: What I learned this week: running functions concurrently

Collapse
 
sergey_telpuk profile image
Sergey Telpuk • Edited

Make with the help of a worker-pool pattern

package main

import (
    "fmt"
    "math/rand"
    "os/exec"
    "sync"
    "time"
)

const countWorkers = 4

type TypeTask func(chan<- string)

func doLS(path string) ([]byte, error) {
    cmd := exec.Command("ls", "-l", path)
    return cmd.CombinedOutput()
}

func jobs(jobs map[string]func(string, chan<- string)) <-chan TypeTask {
    tasks := make(chan TypeTask, len(jobs))
    defer close(tasks)
    for key, value := range jobs {
        tasks <- func(key string, value func(path string, outputs chan<- string)) TypeTask {
            return func(out chan<- string) {
                value(key, out)
            }
        }(key, value)
    }
    return tasks
}

func task(tasks <-chan TypeTask, out chan string) {
    for task := range tasks {
        task(out)
    }
}

func makeWP(tasks <-chan TypeTask, countWR int) <-chan string {
    out := make(chan string, len(tasks))
    defer close(out)

    var wg sync.WaitGroup
    defer wg.Wait()
    wg.Add(countWR)

    for i := 0; i < countWR; i++ {
        go func() {
            task(tasks, out)
            defer wg.Done()
        }()
    }

    return out
}

func main() {
    paths := map[string]func(string, chan<- string){
        "/usr": func(path string, outputs chan<- string) {
            out, _ := doLS(path)
            time.Sleep(time.Duration(rand.Intn(2000)) * time.Millisecond)
            outputs <- string(out)
        },
        "/": func(path string, outputs chan<- string) {
            out, _ := doLS(path)
            time.Sleep(time.Duration(rand.Intn(5000)) * time.Millisecond)
            outputs <- string(out)
        },
    }
    done := make(chan bool)
    go func() {
        tasks := jobs(paths)
        outs := makeWP(tasks, countWorkers)

        for out := range outs {
            fmt.Println(out)
        }
        done <- true
    }()

    <-done
}
Collapse
 
ineedale profile image
Alex Leonhardt

Thanks! Another way to accomplish the task. 👍