使用fanIn函数多路复用Go例程输出

使用fanIn函数多路复用Go例程输出,go,Go,我试图实现一个示例Go代码,用于使用Go例程返回的通道,而主函数中没有任何“读取块”。这里,fanIn函数接受来自另外两个例程的通道,并返回作为输入的通道 这里,预期的输出是来自两个内部例程的随机输出。但实际输出总是一个“ann”后跟一个“john”,在任何情况下都不是随机的 为什么我没有得到随机输出 前往游乐场: 实际产量: you say: ann,0 you say: john,0 you say: ann,1 you say: john,1 ...... 代码

我试图实现一个示例Go代码,用于使用Go例程返回的通道,而主函数中没有任何“读取块”。这里,fanIn函数接受来自另外两个例程的通道,并返回作为输入的通道

这里,预期的输出是来自两个内部例程的随机输出。但实际输出总是一个“ann”后跟一个“john”,在任何情况下都不是随机的

为什么我没有得到随机输出

前往游乐场:

实际产量:

  you say: ann,0 
  you say: john,0
  you say: ann,1
  you say: john,1 
   ......
代码:

主程序包
进口(
“fmt”
“时间”
)
func main(){
期末考试:=fanIn(无聊(“安”)、无聊(“约翰”))
对于i:=0;i<100;i++{

Println(“你说:”,没有特别的原因,这就是安排相关goroutine的方式(基本上,你“幸运”地”得到了一个模式)。你不能依赖它。如果你真的想要一个真实可靠的随机结果,你必须以某种方式手动混合随机性


还有来自(doc:)的
多路复用功能它实际上与你的
fanIn
函数的作用相同。不过,我不认为它在随机性方面会有任何不同。

是什么让你认为它应该是随机的?可能是@JimB的重复?我试图学习如何调用和执行go例程。这里有两个例程并行运行。因为它们正在运行独立地说,我期望随机输出。但我在所有运行中都得到了相同的模式。@Marc我看了你提到的问题。答案是将打印计数增加到20。这里我使用的100仍然不是随机的。我认为Evan关于睡眠的回答和评论是这个问题的正确答案。它提供了更多的见解。@Faisalk:好的,只是w如果某个地方有一些错误的文档,请记住这些文档在技术上不是独立运行的,它们是由单个计划程序安排的(尽管这也是一个实现细节)。许多事情也会影响到这一点,包括GOMAXPROCS>1。只需指出,删除睡眠将“修复”缺乏随机性。或者说睡眠时间的随机性睡眠时间的随机性实际上会增加真正的随机性;完全取消睡眠只会使对go的调度程序的依赖更加明显(尽管go仍然允许以确定性的方式调度它们).事实上,go不需要在goroutines可用时就安排,所以即使是随机睡眠也不能让你摆脱困境。@Evan是的,当睡眠被移除时,它会像预期的那样工作。谢谢你的新见解!!
package main

import (
    "fmt"
    "time"
)

func main() {

    final := fanIn(boring("ann"), boring("john"))

    for i := 0; i < 100; i++ {
        fmt.Println("you say:", <-final)

    }
    time.Sleep(4 * time.Second)
}

func boring(msg string) chan string {
    c1 := make(chan string)
    go func() {
        for i := 0; ; i++ {
            c1 <- fmt.Sprintf("%s,%d", msg, i)
            time.Sleep(time.Second)

        }
    }()
    return c1
}

func fanIn(input1, input2 <-chan string) chan string {
    c := make(chan string)
    go func() {
        for {
            c <- <-input1
        }
    }()
    go func() {
        for {
            c <- <-input2
        }
    }()
    return c
}