go之GopherJS 在 goroutine 中的死锁
为什么下面的代码会出现死锁?我正在尝试将 goroutine 中的某些内容返回到外部
package main
import (
"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]:
.....
请您参考如下方法:
几乎就是它在错误消息中所说的内容。所有的 goroutine 都处于休眠状态。 main不启动任何东西,只是接收一个 channel ,所以它被阻塞了,并且没有其他 goroutines 正在运行,所以不可能 main可能会再次唤醒,因此运行时会出现 panic 。
如果我没记错的话,与常规 Go 不同,如果 main,GopherJS 不会关闭所有内容并退出。退出(部分原因是:这到底意味着什么?最接近 Go 程序的模拟是关闭网页!这有点糟糕。所以 GopherJS 不会那样做。)。所以你在做什么来保持main严格来说,在 GopherJS 中,活着不是必需的。
也就是说,如果你说(例如)time.Sleep(time.Hour)最后,当所有的 goroutine 都还在休眠时(严格来说),main最终会唤醒,运行时知道,所以在这种情况下它不会 panic 。
至于你的实际test功能,一旦你尝试了,你会得到一个相关的错误信息:Uncaught Error: runtime error: cannot block in JavaScript callback, fix by wrapping code in goroutine . test在 channel 上进行阻塞调用,而 GopherJS 不允许在直接从 Javascript 调用的函数中执行此操作,因此它会发生 panic 。 (当我在 playground 中运行它时,我也会得到 Uncaught TypeError: r is not a function ,但这只是早期错误的后果。)
我想你要做的是等待doRequest完成,打印值并返回,但这不起作用。为此,您需要使用 native Javascript promise 或其他一些异步机制。
1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。



