gpt4 book ai didi

go - Golang 中的多个发送者到单个 channel

转载 作者:IT王子 更新时间:2023-10-29 02:10:11 25 4
gpt4 key购买 nike

这个概念解释起来似乎很简单,但实现起来(“正确”)有点难。

tl;dr 是我想运行将输出推送到单个 channel 的多个函数。

作为示例工作测试(具有多个 channel ),详细说明我的问题 https://play.golang.org/p/1ztCvPFLXKv

package main

import (
"fmt"
"time"
)

type intTest struct {
ID int
Number int
}

func modify1(channelID string, res chan []intTest) {
s := []intTest{}
for i := 0; i < 10; i++ {
fmt.Printf("Adding inside: %s\n", channelID)
s = append(s, intTest{i, 0})
time.Sleep(100 * time.Millisecond)
}
res <- s
}
func modify2(channelID string, res chan []intTest) {
s := []intTest{}
for i := 10; i < 20; i++ {
fmt.Printf("Adding inside: %s\n", channelID)
s = append(s, intTest{i, 0})
time.Sleep(200 * time.Millisecond)
}
res <- s
}
func modify3(channelID string, res chan []intTest) {
s := []intTest{}
for i := 20; i < 30; i++ {
fmt.Printf("Adding inside: %s\n", channelID)
s = append(s, intTest{i, 0})
time.Sleep(300 * time.Millisecond)
}
res <- s
}

func main() {
channelA := make(chan []intTest)
channelB := make(chan []intTest)
channelC := make(chan []intTest)

go modify1("A", channelA)
go modify2("B", channelB)
go modify3("C", channelC)

b := append(<-channelA, <-channelB...)
b = append(b, <-channelC...)
fmt.Println(b)
}

输出:

Adding inside: C
Adding inside: A
Adding inside: B
..snip..
Adding inside: C
Adding inside: C
Adding inside: C
[{0 0} {1 0} {2 0} {3 0} {4 0} {5 0} {6 0} {7 0} {8 0} {9 0} {10 0} {11 0} {12 0} {13 0} {14 0} {15 0} {16 0} {17 0} {18 0} {19 0} {20 0} {21 0} {22 0} {23 0} {24 0} {25 0} {26 0} {27 0} {28 0} {29 0}]

但是,我想实现这样的目标:https://play.golang.org/p/qvC88LwkanY输出:

Adding inside: C
Adding inside: A
Adding inside: B
..snip
Adding inside: B
Adding inside: A
Adding inside: C
[{0 0} {1 0} {2 0} {3 0} {4 0} {5 0} {6 0} {7 0} {8 0} {9 0}]

但如图所示,函数 modify2 和 modify3 在视觉上似乎从未被添加。

这可能吗,还是顶层样本更可行?

最佳答案

I would like to achieve something like this

channelA := make(chan []intTest)
go modify1("A", channelA)
go modify2("B", channelA)
go modify3("C", channelA)

Is this possible, or is the top sample more feasible?

是的:您可以在多个 goroutine 中使用单个 channel ——这就是 channel 的设计目的。

but as shown the functions modify2 & modify3 visually seems like they never get added.

你遇到的问题是你只调用了一次接收运算符(operator):

b := append(<-channelA)
fmt.Println(b)

当您的 main goroutine 退出时,其他两个 goroutine 要么被阻塞等待发送它们的结果,要么仍在构建它们的结果。

如果将 main() 函数更改为此,您可以看到如果另一个例程准备好接收所有三个工作程序将通过 channel 发送它们的结果(因为您使用了无缓冲 channel ,发送将阻塞,直到接收者准备好):

func main() {
ch := make(chan []intTest)

go modify1("A", ch)
go modify2("B", ch)
go modify3("C", ch)
fmt.Println(<-ch)
fmt.Println(<-ch)
fmt.Println(<-ch)
}

哪些输出:

Adding inside: C
Adding inside: A
Adding inside: B
Adding inside: A
Adding inside: A
Adding inside: B
Adding inside: C
Adding inside: A
Adding inside: B
Adding inside: A
Adding inside: A
Adding inside: B
Adding inside: C
Adding inside: A
Adding inside: A
Adding inside: B
Adding inside: A
Adding inside: C
Adding inside: A
Adding inside: B
[{0 0} {1 0} {2 0} {3 0} {4 0} {5 0} {6 0} {7 0} {8 0} {9 0}]
Adding inside: C
Adding inside: B
Adding inside: B
Adding inside: C
Adding inside: B
Adding inside: C
Adding inside: B
[{10 0} {11 0} {12 0} {13 0} {14 0} {15 0} {16 0} {17 0} {18 0} {19 0}]
Adding inside: C
Adding inside: C
Adding inside: C
[{20 0} {21 0} {22 0} {23 0} {24 0} {25 0} {26 0} {27 0} {28 0} {29 0}]

然后您可以更改该代码以在输出之前将接收到的元素附加到单个列表,或者以您喜欢的任何方式格式化接收到的元素。

I thought it's almost like popping onto a stack and then pulling the whole stack

对于一个初始化的、未关闭的缓冲 channel ,发送语句将一个元素放入队列中,接收操作从队列中弹出一个元素并将其返回。它是先进先出 (FIFO) 顺序,因此它是一个队列而不是堆栈。在上面的示例中, channel 是无缓冲的,因此发送必须等待 goroutine 准备好接收,接收必须等待 goroutine 准备好发送。 Main 也是一个 goroutine。

关于go - Golang 中的多个发送者到单个 channel ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48956306/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com