我刚刚开始学习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个功能并返回&#34;完成&#34;声明。
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的相同频道
,也不会覆盖价值答案 0 :(得分:0)
据我所知,您将频道视为变量。一个可以保存一些值的变量。因此,如果有一些value1
并且你写了另一个value2
,你基本上希望value1
消失。这是错的。
尝试将频道看作缓冲区或优先级队列(有些人发现它粗略比较)。频道有它的大小(你的第三个变量3
),它告诉它可以同时有多少个值。一旦你在频道中放置了某些内容,就可以将其视为优先级等于完成此例程所需时间的进程。
因此,在您的情况下,您使用go wait()
将3个元素放入优先级队列中,然后从w1, w2, w3 := <-c, <-c, <-c
的队列中提取。所以什么都不会被覆盖。
答案 1 :(得分:0)
无缓冲通道在发送数据之前同步。因此,在这种情况下,您在分配行中对<-c
的连续调用会阻塞,直到另一端的等待函数发送完成为止。
马库斯提出了一个很好的观点,应该指出这个w1, w2, w3 := <-c, <-c, <-c
只有在你等不同等待函数的等待时间错开时才有效。如果这些函数在通道上发送数据之前等待了任意时间,则无法保证将w2分配给wait2发送的结果。它只会被设置为通过频道发送的第二个值。