Go 戈朗的生产者和消费者

Go 戈朗的生产者和消费者,go,goroutine,Go,Goroutine,尝试运行以下代码(生产者和消费者),以了解golang中的goroutines和channel(从下面的代码片段中删除了包和导入): 根据我对goroutines和channel的了解: 当我们使用go关键字从main()调用product()和consume()时,go运行时将启动2个goroutine(java世界中的线程,但不是实际的OS线程),main()goroutine将在“msgs频道无缓冲。这意味着要完成发送,必须有相应的接收操作,该操作也可以完成。这在goroutine之间提供

尝试运行以下代码(生产者和消费者),以了解golang中的goroutines和channel(从下面的代码片段中删除了包和导入):

根据我对goroutines和channel的了解:
当我们使用go关键字从main()调用product()和consume()时,go运行时将启动2个goroutine(java世界中的线程,但不是实际的OS线程),main()goroutine将在“msgs频道无缓冲。这意味着要完成发送,必须有相应的接收操作,该操作也可以完成。这在goroutine之间提供了一个同步点

如果您只需在示例中添加几个print语句,就很容易看到


producer中的print语句将被打印,并且在for循环退出后,msgs通道将立即关闭。我不明白你在问什么。那为什么在输出中,“关闭通道之前”和“传递真值之前”的打印语句在“消费者:8”之后打印,即在所有MSG被消费之后?在无缓冲通道上的发送和接收是同步的。这些文档可能会有所帮助:您也可以通过编辑原始文档来看到这一点,例如
var msgs=make(chan int,99)
;有足够空间的缓冲通道。在这种情况下,main可能会在消费者可以消费任何东西/所有东西之前退出(确切的顺序尚未定义)。现在完美才有意义。谢谢你的详细解释,@JimB。我已经厌倦了将msgs频道作为缓冲区。在consume()中添加了一些打印语句。每次运行代码时,我都会看到“fmt.Println(“调用完成后”)”被打印出来,甚至在此之后,我还可以看到consume()函数内部的打印语句被打印出来。无论何时“@srock:consumer都可以自由运行直到main返回,所以它不可能打印出

var done = make(chan bool)
var msgs = make(chan int)

func produce() {
    for i := 0; i < 10; i++ {
            msgs <- i
    }
    fmt.Println("Before closing channel")
    close(msgs)
    fmt.Println("Before passing true to done")
    done <- true
}

func consume() {
    for {
            msg := <-msgs
            time.Sleep(100 * time.Millisecond)
            fmt.Println("Consumer: ", msg)
    }
}

func main() {
    go produce()
    go consume()
    <-done
    fmt.Println("After calling DONE")
}
Consumer:  0
Consumer:  1
Consumer:  2
Consumer:  3
Consumer:  4
Consumer:  5
Consumer:  6
Consumer:  7
Consumer:  8
Before closing channel
Before passing true to done
After calling DONE
func produce() {
    for i := 0; i < 4; i++ {
        fmt.Println("sending")
        msgs <- i
        fmt.Println("sent")
    }
    fmt.Println("Before closing channel")
    close(msgs)
    fmt.Println("Before passing true to done")
    done <- true
}

func consume() {
    for msg := range msgs {
        fmt.Println("Consumer: ", msg)
        time.Sleep(100 * time.Millisecond)

    }
}
sending
Consumer:  0
sent
sending
Consumer:  1
sent
sending
Consumer:  2
sent
sending
Consumer:  3
sent
Before closing channel
Before passing true to done
After calling DONE