最近刚开始学习Go,学习Goroutine的时候很迷茫。这是我的代码。这打算同时完成3个过程。package mainimport ( "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, <-clog.Print("finished")fmt.Println(w1, w2, w3)但是,如您所见,输出正是我所期望的。它同时处理 3 个函数并返回“完成”语句。2015/11/25 09:41:31 started2015/11/25 09:41:32 waited 1 sec2015/11/25 09:41:33 waited 2 sec2015/11/25 09:41:34 waited 3 sec2015/11/25 09:41:34 finishedwait1 finishedwait2 finishedwait3 finished为什么没有必要创建 3 个不同的通道,如 c1、c2、c3...?为什么即使我使用名为 c 的同一个通道,值也不会被覆盖?
2 回答
郎朗坤
TA贡献1921条经验 获得超9个赞
据我了解,您将渠道视为一个变量。一个可以保存一些值的变量。因此,如果有一些,value1
而您又写了另一个,value2
那么您基本上预计它们value1
会消失。这是错误的。
尝试将通道视为缓冲区或优先级队列(有些人认为比较粗略)。通道有它的大小(你的第三个变量3
),它告诉它可以同时有多少个值。一旦你在通道中放入了一些东西,你就可以将它看作是优先级等于完成这个 go-routine 所需时间的进程。
因此,在您的情况下,您将 3 个元素放入优先级队列中go wait()
,然后使用w1, w2, w3 := <-c, <-c, <-c
. 所以没有什么会被覆盖。
Qyouu
TA贡献1786条经验 获得超11个赞
无缓冲通道在发送数据之前同步。因此,在这种情况下,您<-c
在分配行中的连续调用将阻塞,直到另一端的等待函数通过发送某些内容为止。
不过,Markus 提出了一个很好的观点,应该指出这w1, w2, w3 := <-c, <-c, <-c
只是因为您已经错开了不同等待功能的等待时间。如果这些函数在通道上发送数据之前等待了任意时间,您将无法保证 w2 被分配给从 wait2 发送的结果。它只会被设置为通过通道发送的第二个值。
- 2 回答
- 0 关注
- 141 浏览
添加回答
举报
0/150
提交
取消