Go Channel - 我的代码看起来覆盖了频道,但有效。

时间:2015-11-25 00:54:05

标签: go channel goroutine

我刚刚开始学习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的相同频道

,也不会覆盖价值

2 个答案:

答案 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发送的结果。它只会被设置为通过频道发送的第二个值。