Golang 生产者通道作为参数或返回值

Mic*_*ner 6 channel go

据我所知,在函数中处理生产者通道有两种方法:(1)作为参数或(2)作为返回值。对于 (1),该函数是通道的所有者,而 (2) 中的所有者是未知的(对于该函数。

哪个更惯用,producer1或者producer2?我是否发现了劣势?有没有具体的使用场景?

下面是(1)和(2)的实现:

func producer1(numbers []int) <-chan int {
    out := make(chan int)
    go func() {
        defer close(out)
        for _, n := range numbers {
            out <- n
        }
    }()
    return out
}

func producer2(numbers []int, out <-chan int) {
    go func() {
        defer close(out)
        for _, n := range numbers {
            out <- n
        }
    }()
}
Run Code Online (Sandbox Code Playgroud)

LeG*_*GEC 6

恕我直言:这取决于。

producer1对于该通道的行为和生命周期非常明确(这可能是一件好事),
producer2允许您将这些值的发射插入到一些更大的上下文中(这也可能是一件好事)。

“好东西”的概念实际上取决于您打算如何在这些功能之外使用这些渠道。


一项额外说明:producer2不处理通道的创建,我还将从此函数中删除关闭通道的行。

如果您想知道 Producer2 是否已完成其任务,您可以使用其他方式来发出信号,例如:

func producer2(numbers []int, out <-chan int) (done <-chan struct{}) {
    done = make(chan struct{})

    go func() {
        defer close(done)
        for _, n := range numbers {
            out <- n
        }
    }()

    return done
}

// a caller may check '<-done' to see if producer2 has finished feeding all
// of its numbers into the 'out' channel
Run Code Online (Sandbox Code Playgroud)


was*_*mup 4

使用ch := producer1([]int{1, 2, 3, 4})简化了这两行:

out := make(chan int)
producer2([]int{10, 20, 30, 40}, out)
Run Code Online (Sandbox Code Playgroud)

成一行:

ch := producer1([]int{1, 2, 3, 4})
Run Code Online (Sandbox Code Playgroud)

因此,当您多次需要时,第一个用例是代码简化DRY )。

哪个更惯用,producer1或者producer2

对于您的示例用例producer1

我是否发现了劣势?

是的

有没有具体的使用场景?

干燥


注意:producer2您必须使用像这样的仅限 tx 通道,out chan<- int而不是out <-chan int(仅限 rx 通道)。就像这个工作代码(运行缓冲非缓冲):

package main

import "fmt"

func producer1(numbers []int) <-chan int {
    out := make(chan int)
    go func() {
        defer close(out)
        for _, n := range numbers {
            out <- n
        }
    }()
    return out
}

func main() {
    ch := producer1([]int{1, 2, 3, 4})
    for v := range ch {
        fmt.Println(v)
    }
    out := make(chan int)
    producer2([]int{10, 20, 30, 40}, out)
    for v := range out {
        fmt.Println(v)
    }
}

func producer2(numbers []int, out chan<- int) {
    go func() {
        defer close(out)
        for _, n := range numbers {
            out <- n
        }
    }()
}
Run Code Online (Sandbox Code Playgroud)