为什么以下代码中出现死锁?我正在尝试将某些东西从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
不启动任何东西,只接收一个通道,因此它被阻塞,并且没有其他goroutine正在运行,因此main
不可能再次唤醒,因此运行时会出现恐慌。
如果我没记错的话,与普通的Go语言不同,GopherJS不会关闭所有文件并在main
退出的情况下退出(部分原因是:那到底是什么意思?与Go程序最接近的类比就是关闭网页!的问题。所以GopherJS不会那样做。)。因此,严格来说,在GopherJS中,无需执行使main
保持 Activity 状态的操作。
也就是说,如果您在末尾说(例如)time.Sleep(time.Hour)
,则在所有goroutine仍处于睡眠状态(严格来说)时,main
最终将唤醒,运行时知道,因此在这种情况下不会惊慌。
至于您的实际test
函数,一旦尝试使用它,您会收到一条相关的错误消息:Uncaught Error: runtime error: cannot block in JavaScript callback, fix by wrapping code in goroutine
。 test
在通道上进行了阻塞调用,而GopherJS不允许在直接从Javascript调用的函数中进行此操作,因此会感到恐慌。 (当我在playground中运行它时,我也得到Uncaught TypeError: r is not a function
,但这只是先前错误的结果。)
我认为您正在尝试做的是等待doRequest
完成,打印值并返回,但这是行不通的。为此,您需要使用本机Javascript Promise或其他异步机制。