登录
首页 >  Golang >  Go问答

在选择中未准备好向通道发送值

来源:stackoverflow

时间:2024-04-15 08:57:37 438浏览 收藏

你在学习Golang相关的知识吗?本文《在选择中未准备好向通道发送值》,主要介绍的内容就涉及到,如果你想提升自己的开发能力,就不要错过这篇文章,大家要知道编程理论基础和实战操作都是不可或缺的哦!

问题内容

package main

import (
    "fmt"
    "time"
)

func main() {

    ch := make(chan int)
    go func() {
        fmt.Printf("func at %d\n", time.Now().UnixNano())
        select {
        case ch <- 1:
            fmt.Println("running send")
        default:
            fmt.Println("running default")
        }
    }()

    time.Sleep(100 * time.Millisecond)
    fmt.Printf("main at %d\n", time.Now().UnixNano())
    fmt.Println(<-ch)
}

演示在这里

研究了一天还是无法解释为什么case ch <-1:还没有准备好,选择default case运行。当然,这会导致死锁!


解决方案


来自doc

如果通道没有缓冲,则发送方会阻塞,直到接收方收到该值。如果通道有缓冲区,则发送方只会阻塞,直到该值被复制到缓冲区为止;如果缓冲区已满,这意味着等待某个接收器检索到值。

一种方法是使用它。这是首先生成的接收者 goroutine。另外,如果接收器尚未准备好,则将采用默认情况。如果准备好了,具体的案例也会准备好。如果您运行多次,您可以看到任一情况发生。

package main

import (
    "fmt"
    "time"
)

func main() {
    ch := make(chan int)
    // goroutine acts as the reciever
    go func() {
        fmt.printf("main at %d\n", time.now().unixnano())
        fmt.println(<-ch)
    }()
    go func() {
        fmt.printf("func at %d\n", time.now().unixnano())
        select {
        case ch <- 1:
            fmt.println("running send")
        default:
            fmt.println("running default")
        }
    }()
    time.sleep(1 * time.second) // wait for the goroutines
}

另一种解决方案是使用缓冲通道:

package main

import (
    "fmt"
    "time"
)

func main() {

    ch := make(chan int, 1)
    go func() {
        fmt.printf("func at %d\n", time.now().unixnano())
        select {
        case ch <- 1:
            fmt.println("running send")
        default:
            fmt.println("running default")
        }
    }()

    time.sleep(100 * time.millisecond)
    fmt.printf("main at %d\n", time.now().unixnano())
    fmt.println(<-ch)
}

另外,请阅读 stackoverflow 上的 thread

您已经使用 make(chan int) 创建了没有缓冲的 go 通道。您需要一个缓冲通道(不一定会阻塞),您应该使用 make(chan int, 20),其中 20 是通道的大小

无缓冲通道的特点是它们也是同步的,因此它们总是在写入和读取时阻塞。当缓冲区填满时,缓冲通道也会发生同样的情况。

尝试下面的代码

package main

import (
    "fmt"
    "time"
)

func main() {

    ch := make(chan int, 20)
    go func() {
        fmt.Printf("func at %d\n", time.Now().UnixNano())
        select {
        case ch <- 1:
            fmt.Println("running send")
        default:
            fmt.Println("running default")
        }
    }()

    time.Sleep(100 * time.Millisecond)
    fmt.Printf("main at %d\n", time.Now().UnixNano())
    fmt.Println(<-ch)
}

文中关于的知识介绍,希望对你的学习有所帮助!若是受益匪浅,那就动动鼠标收藏这篇《在选择中未准备好向通道发送值》文章吧,也可关注golang学习网公众号了解相关技术文章。

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>