为了账号安全,请及时绑定邮箱和手机立即绑定

GopherJS 在 goroutine 中的死锁

GopherJS 在 goroutine 中的死锁

Go
慕桂英4014372 2022-05-18 10:15:01
为什么下面的代码会出现死锁?我正在尝试将 goroutine 中的某些内容返回到外部package mainimport (    "fmt"    "syscall/js"    "time")func test(this js.Value, i []js.Value) interface{} {    done := make(chan string, 1)    go func() {        doRequest := func(this js.Value, i []js.Value) interface{} {            time.Sleep(time.Second)            return 0        }        js.Global().Set("doRequest", js.FuncOf(doRequest))        args := []js.Value{js.ValueOf("url")}        var x js.Value        doRequest(x, args)        done <- "true"    }()    aa := <-done    fmt.Println(aa)    return 0}func main() {    c := make(chan bool)    js.Global().Set("test", js.FuncOf(test))    <-c}当我在浏览器上运行它并调用 test() 时,将显示以下错误fatal error: all goroutines are asleep - deadlock!goroutine 1 [chan receive]:.....
查看完整描述

2 回答

?
qq_遁去的一_1

TA贡献1725条经验 获得超7个赞

几乎就是它在错误消息中所说的内容。所有的 goroutine 都处于休眠状态。 main不启动任何东西,只是接收一个通道,所以它被阻塞了,并且没有其他 goroutines 正在运行,所以main不可能再次唤醒,所以运行时恐慌。

如果我没记错的话,与常规 Go 不同,GopherJS 不会关闭所有内容并在退出时main退出(部分原因是:这到底意味着什么?最接近 Go 程序的模拟是关闭网页!哪一种糟透了。所以 GopherJS 不会那样做。)。因此,严格来说,在 GopherJS 中,您为保持main活力所做的一切是不必要的。

也就是说,如果你在最后说(例如)time.Sleep(time.Hour),那么当所有 goroutines 仍然处于睡眠状态(严格来说)时,main最终会唤醒,运行时知道,所以在这种情况下它不会恐慌。

至于您的实际test功能,一旦您尝试过,您会收到相关的错误消息:Uncaught Error: runtime error: cannot block in JavaScript callback, fix by wrapping code in goroutinetest在通道上进行阻塞调用,而 GopherJS 不允许在直接从 Javascript 调用的函数中执行此操作,因此它会发生恐慌。(当我在操场上运行它时,也得到Uncaught TypeError: r is not a function了工作。为此,您需要使用本机 Javascript 承诺或其他一些异步机制。doRequest


查看完整回答
反对 回复 2022-05-18
?
慕森卡

TA贡献1806条经验 获得超8个赞

func main() {

    c := make(chan bool)

    js.Global().Set("test", js.FuncOf(test))

    <-c

}

您已经创建了一个通道c,然后等待从它接收一个值。注意函数c的局部变量如何main。对的引用c永远不会在程序的其他任何地方传递,因此永远不会在c通道上发送值,因此您的主 goroutine 将永远等待接收。


查看完整回答
反对 回复 2022-05-18
  • 2 回答
  • 0 关注
  • 108 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号