openlang

请帮我看看 go 管道的实现(还在学习这门语言)

大家好,

我正在学习 go 和它的并发功能,“管道”是常见模式之一。下面是我的实现,想请大家看看,并建议还有什么可以改进的地方

package main

import (
    "context"
    "fmt"
    "runtime"
    "sync"
    "time"
)

func generate(ctx context.Context, inputs chan<- int) {
    defer close(inputs)
    item := 0
    for {
        select {
        case inputs ← item:
            item++
            time.Sleep(60 * time.Millisecond)
        case <-ctx.Done():
            fmt.Println("Ending producer goroutine and inputs channel gracefuly.")
            return
        }
    }
}

func process(inputs <-chan int, outputs chan<- int, group *sync.WaitGroup) {
    defer group.Done()
    for item := range inputs {
        outputs ← item * item
    }
}

func collect(outputs <-chan int) {
    for square := range outputs {
        fmt.Printf("square %d\n", square)
    }
}

func finish(group *sync.WaitGroup, outputs chan<- int) {
    group.Wait()
    close(outputs)
    fmt.Println("Ending coordinator/worker goroutines and outputs channel gracefuly.")
}

func main() {
    ctx, cancel := context.WithTimeout(
        context.Background(),
        1800*time.Millisecond
    )
    defer cancel()

    inputs := make(chan int, 960)
    outputs := make(chan int, 960)

    go generate(ctx, inputs)

    var group sync.WaitGroup
    for range 4 {
        group.Add(1)
        go process(inputs, outputs, &group)
    }

    go finish(&group, outputs)

    collect(outputs)

    fmt.Printf("Pipeline drained completly !\n")
    fmt.Printf("Goroutine count : %d\n", runtime.NumGoroutine()) // expected to be 1
}

另外,还有哪些重要且常用的并发模式值得学习,比如 pubsub。

祝好,

FV

从英语翻译查看原文

后续讨论 3

顺着彼此的依据读下去
  1. 固定链接

    也许可以看看其他 Go 管道实现,以及这种模式背后的想法。这样就能先更好地理解问题,再决定自己的实现需要哪些修改…

    只是我的一点建议…

    从英语翻译查看原文
  2. 固定链接

    如果这里的“管道”是指 Linux shell 那种管道,那这不是。那种管道的好处是把同步机制隐藏起来。因此,看到这里有 Sync 代码,我有些困惑。

    从英语翻译查看原文

同一个问题的其他角度

  1. 把函数转成深层处理器的续体

    文档中深层处理器的例子有这么一段。 计算 f 本身也可以执行效果。当 f 执行 Yield 时,它的任务被暂停并放入就绪任务队列,然后调度器运行队列中的下一个任务。如果效果是 Fork f,就暂停当前任务,通过尾调用 spawn f 立即运行新任务…

    回复 3最近活动 ocaml