【发布时间】:2018-08-04 00:12:48
【问题描述】:
这个概念似乎很容易解释,但实施起来有点困难(“正确”)。
tl;dr 是我想运行多个将输出推送到单个通道的函数。
作为一个示例工作测试(具有多个通道),详细说明我的问题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 在视觉上似乎从未被添加。
这可能吗,还是上面的样本更可行?
【问题讨论】:
-
如果你想让他们都推送到同一个频道,为什么不让他们都推送到播放链接中的同一个频道?
-
你在第二个例子中的问题是你只从频道接收一次,这意味着只有 第一个 发送者到频道(在这种情况下,A,虽然它在技术上是不确定的)被接收。如果您需要所有 3 个的输出,则需要从通道接收 3 次才能获得所有输出(发送到通道不仅仅是神奇地连接所有这些值!)
-
是否要等到所有例程完成后再打印结果?
-
太棒了,我想我可能误解了阻塞/发送的概念,根据我的大脑,通过发送到通道,它会在 go 例程完成后全部被拉出,几乎就像跳到一个堆栈,然后拉整个堆栈。但我现在确实明白我必须“为每次推动而拉动”。非常感谢大家:)
-
play.golang.org/p/_v1r_cQ5gAS 看来 Body.Close() 并没有关闭 goroutine。
标签: go concurrency channels