涛子 - 简单就是美

成单纯魁增,永继振国兴,克复宗清政,广开家必升

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

https://dev.to/karanpratapsingh/go-course-advanced-concurrency-patterns-3ap4

1. Generator

package main

import "fmt"

func generator() <-chan int {
    ch := make(chan int)

    go func() {
        for i := 0; ; i++ {
            ch <- i
        }
    }()

    return ch
}

func main() {
    ch := generator()

    for i := 0; i < 5; i++ {
        value := <-ch
        fmt.Println(value)
    }
}

2. fanIn

package main

import (
    "fmt"
    "sync"
)

func generateWork(work []int) <-chan int {
    ch := make(chan int)

    go func() {
        defer close(ch)

        for _, w := range work {
            ch <- w
        }
    }()

    return ch
}

func fanIn(in ...<-chan int) <-chan int {
    var wg sync.WaitGroup
    out := make(chan int)

    wg.Add(len(in))

    for _, i := range in {
        go func(ch <-chan int) {
            for {
                value, ok := <-ch
                if !ok {
                    wg.Done()
                    break
                }
                out <- value
            }
        }(i)
    }

    go func() {
        wg.Wait()
        close(out)
    }()

    return out
}

func main() {
    in1 := generateWork([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})
    in2 := generateWork([]int{11, 12, 13, 14, 15, 16, 17, 18, 19, 20})

    out := fanIn(in1, in2)
    for value := range out {
        fmt.Println(value)
    }
}

3. Fan-out

package main

import "fmt"

func generateWork(work []int) <-chan int {
    ch := make(chan int)

    go func() {
        defer close(ch)

        for _, w := range work {
            ch <- w
        }
    }()

    return ch
}

func fanOut(in <-chan int) <-chan int {
    ch := make(chan int)

    go func() {
        defer close(ch)

        for value := range in {
            ch <- value
        }
    }()

    return ch
}

func main() {
    work := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
    in := generateWork(work)

    out1 := fanOut(in)
    out2 := fanOut(in)
    out3 := fanOut(in)
    out4 := fanOut(in)

    for range work {
        select {
        case value := <-out1:
            fmt.Println("output 1 got: ", value)

        case value := <-out2:
            fmt.Println("output 2 got: ", value)

        case value := <-out3:
            fmt.Println("output 3 got: ", value)

        case value := <-out4:
            fmt.Println("output 4 got: ", value)
        }
    }
}

4. Pipeline

package main

import (
    "fmt"
    "math"
)

func generateWork(work []int) <-chan int {
    ch := make(chan int)

    go func() {
        defer close(ch)

        for _, w := range work {
            ch <- w
        }
    }()

    return ch
}

func filter(in <-chan int) <-chan int {
    ch := make(chan int)

    go func() {
        defer close(ch)

        for i := range in {
            if i%2 == 0 {
                ch <- i
            }
        }
    }()

    return ch
}

func square(in <-chan int) <-chan int {
    ch := make(chan int)

    go func() {
        defer close(ch)

        for i := range in {
            value := math.Pow(float64(i), 2)
            ch <- int(value)
        }
    }()

    return ch
}

func half(in <-chan int) <-chan int {
    ch := make(chan int)

    go func() {
        defer close(ch)

        for i := range in {
            ch <- i / 2
        }
    }()

    return ch
}

func main() {
    in := generateWork([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})

    out := filter(in)
    out = square(out)
    out = half(out)

    for value := range out {
        fmt.Println(value)
    }
}

5. Worker Pool

package main

import (
    "fmt"
    "sync"
)

const totalworkers = 2
const totaljobs = 10

func worker(id int, jobs <-chan int, results chan<- int) {
    var wg sync.WaitGroup

    for j := range jobs {
        wg.Add(1)

        go func(job int) {
            defer wg.Done()

            fmt.Printf("worker %d startted job %d\n", id, job)

            // Do work and send result
            result := job * 2
            results <- result

            fmt.Printf("worker %d finished job %d\n", id, job)
        }(j)
    }

    wg.Wait()
}

func main() {
    jobs := make(chan int, totaljobs)
    results := make(chan int, totaljobs)

    for w := 0; w < totalworkers; w++ {
        go worker(w, jobs, results)
    }

    // send jobs
    for i := 0; i < totaljobs; i++ {
        jobs <- i
    }
    close(jobs)

    // receive results
    for i := 0; i < totaljobs; i++ {
        <-results
    }
    close(results)
}

6. Queuing

package main

import (
    "fmt"
    "sync"
    "time"
)

const limit = 4
const work = 100

func process(wg *sync.WaitGroup, work int, queue chan struct{}) {
    queue <- struct{}{}

    go func() {
        defer wg.Done()

        time.Sleep(time.Second * 1)
        fmt.Println("processed: ", work)

        <-queue
    }()
}

func main() {
    var wg sync.WaitGroup

    fmt.Println("Queue limit: ", limit)
    queue := make(chan struct{}, limit)

    wg.Add(work)
    for w := 0; w < work; w++ {
        process(&wg, w, queue)
    }

    wg.Wait()
    close(queue)
    fmt.Println("work complete")
}
posted on 2023-03-30 10:04  北京涛子  阅读(13)  评论(0编辑  收藏  举报