Go中select语句的正确用法是什么?

Go中select语句的正确用法是什么?,select,go,concurrency,Select,Go,Concurrency,大家好 我一直在学习go的基本原理,以及如何使用其基于通道的并发范式 然而,在玩我编写的专注于select语句的代码时,我发现了一个奇怪的行为: func main() { even := make(chan int) odd := make(chan int) quit := make(chan bool) //send go send(even, odd, quit) //receive receive(even, odd, qui

大家好

我一直在学习go的基本原理,以及如何使用其基于通道的并发范式

然而,在玩我编写的专注于select语句的代码时,我发现了一个奇怪的行为:

func main() {
    even := make(chan int)
    odd := make(chan int)
    quit := make(chan bool)

    //send
    go send(even, odd, quit)

    //receive
    receive(even, odd, quit)
    fmt.Println("Exiting")
}

func send(e, o chan<- int, q chan<- bool) {
    for i := 0; i < 100; i++ {
        if i%2 == 0 {
            e <- i
        } else {
            o <- i
        }
    }
    close(e)
    close(o)
    q <- true
    close(q)
}

func receive(e, o <-chan int, q <-chan bool) {
    for cont, i := true, 0; cont; i++ {
        fmt.Println("value of i", i, cont)
        select {
        case v := <-e:
            fmt.Println("From even channel:", v)
        case v := <-o:
            fmt.Println("from odd channel:", v)
        case v := <-q:
            fmt.Println("Got exit message", v)
            // return // have also tried this instead
            cont = false
        }
    }
}
我已经尝试过搜索case语句的正确用法,但是我没有找到代码中的问题

似乎同样的行为也可以在运动场上重现:


感谢您关注我的问题。

程序正在打印0,因为封闭通道上的接收返回零值。这里有一种方法可以实现你的目标

首先,消除
q
通道。关闭
o
e
通道足以表明发送方已完成

func send(e, o chan<- int, q chan<- bool) {
    for i := 0; i < 100; i++ {
        if i%2 == 0 {
            e <- i
        } else {
            o <- i
        }
    }
    close(e)
    close(o)
}

func send(e,o chanWell,我发现删除close()函数完全使程序按我所期望的那样运行,这类函数仍然是一个非常有趣的行为。我建议您使用书签。当我学习这些内容时,它对我的帮助很大。很好,我不知道从一个通道检索时,除了发送值本身之外,还有第二个值指示该通道是否打开或者不是。谢谢!请注意,第二个值并不表示通道是否关闭,而是表示(第一个)值是否为零值,因为通道已关闭。如果您有缓冲通道,则如果通道的缓冲区中仍有数据,则即使通道关闭,该布尔值仍将为false。例如:
func send(e, o chan<- int, q chan<- bool) {
    for i := 0; i < 100; i++ {
        if i%2 == 0 {
            e <- i
        } else {
            o <- i
        }
    }
    close(e)
    close(o)
}
func receive(e, o <-chan int, q <-chan bool) {

    for e != nil && o != nil {
        select {
        case v, ok := <-e:
            if !ok {
                e = nil
                continue
            }
            fmt.Println("From even channel:", v)
        case v, ok := <-o:
            if !ok {
                o = nil
                continue
            }
            fmt.Println("From odd channel:", v)
        }
    }
}