转到频道 - 我的代码看起来会覆盖频道但有效。

最近刚开始学习Go,学习Goroutine的时候很迷茫。这是我的代码。这打算同时完成3个过程。


package main


import (

    "fmt"

    "log"

    "time"

)


func wait1(c chan string) {

    time.Sleep(1 * time.Second)

    log.Print("waited 1 sec")

    c <- "wait1 finished\n"


}


func wait2(c chan string) {

    time.Sleep(2 * time.Second)

    log.Print("waited 2 sec")

    c <- "wait2 finished\n"

}


func wait3(c chan string) {

    time.Sleep(3 * time.Second)

    log.Print("waited 3 sec")

    c <- "wait3 finished\n"

}


func main() {

    c := make(chan string, 3)

    log.Print("started")

    go wait1(c)

    go wait2(c)

    go wait3(c)

    w1, w2, w3 := <-c, <-c, <-c

    log.Print("finished")

    fmt.Println(w1, w2, w3)

}

对我来说,这部分看起来将不同的函数输入到名为 c 的同一个通道中,并尝试打印从 c 接收到的值。


c := make(chan string, 3)

log.Print("started")

go wait1(c)

go wait2(c)

go wait3(c)

w1, w2, w3 := <-c, <-c, <-c

log.Print("finished")

fmt.Println(w1, w2, w3)

但是,如您所见,输出正是我所期望的。它同时处理 3 个函数并返回“完成”语句。


2015/11/25 09:41:31 started

2015/11/25 09:41:32 waited 1 sec

2015/11/25 09:41:33 waited 2 sec

2015/11/25 09:41:34 waited 3 sec

2015/11/25 09:41:34 finished

wait1 finished

wait2 finished

wait3 finished

为什么没有必要创建 3 个不同的通道,如 c1、c2、c3...?为什么即使我使用名为 c 的同一个通道,值也不会被覆盖?


慕运维8079593
浏览 142回答 2
2回答

郎朗坤

据我了解,您将渠道视为一个变量。一个可以保存一些值的变量。因此,如果有一些,value1而您又写了另一个,value2那么您基本上预计它们value1会消失。这是错误的。尝试将通道视为缓冲区或优先级队列(有些人认为比较粗略)。通道有它的大小(你的第三个变量3),它告诉它可以同时有多少个值。一旦你在通道中放入了一些东西,你就可以将它看作是优先级等于完成这个 go-routine 所需时间的进程。因此,在您的情况下,您将 3 个元素放入优先级队列中go wait(),然后使用w1, w2, w3 := <-c, <-c, <-c.&nbsp;所以没有什么会被覆盖。

Qyouu

无缓冲通道在发送数据之前同步。因此,在这种情况下,您<-c在分配行中的连续调用将阻塞,直到另一端的等待函数通过发送某些内容为止。不过,Markus 提出了一个很好的观点,应该指出这w1, w2, w3 := <-c, <-c, <-c只是因为您已经错开了不同等待功能的等待时间。如果这些函数在通道上发送数据之前等待了任意时间,您将无法保证 w2 被分配给从 wait2 发送的结果。它只会被设置为通过通道发送的第二个值。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go