http.Get() 的死块

Dead block with http.Get()

根据 FuncOf 文档:

calling any async JavaScript API, which requires the event loop, like fetch (http.Client), will cause an immediate deadlock. Therefore a blocking function should explicitly start a new goroutine.

所以,我写了下面的代码:

package main

import (
    "bytes"
    "fmt"
    "io"
    "net/http"
    "syscall/js"
)
func (db *DataBase) init(dataSet, table string) {
    var Ok, Err, Upgrade js.Func
    db.Request = Window.Get("indexedDB").Call("open", dataSet, 1)

    done := make(chan *bytes.Buffer)

    Upgrade = js.FuncOf(func(this js.Value, args []js.Value) interface{} {
        defer Upgrade.Release()
        db.Data = this.Get("result")

        fullUrlFile = "https://i.imgur.com/m1UIjW1.jpg"

        go func(fullUrlFile string) {
            var blob *bytes.Buffer

            r, e := http.Get(fullUrlFile)
            if e != nil {
                panic(e)
            }
            defer r.Body.Close()
            buildFileName()
            // Create blob
            var dest []byte

            blob = bytes.NewBuffer(dest)
            io.Copy(blob, r.Body)
            done <- blob
        }(fullUrlFile)

        blob := <-done

        Store := db.Data.Call("createObjectStore", table, map[string]interface{}{"keyPath": "id"}) 
        Store.Call("add", map[string]interface{}{"id": "00-03", "name": "Karam", "age": 19, "email": "kenny@planet.org", "image": blob})

        Window.Call("alert", "First record posted.")
        return nil
    })

   db.Request.Set("onupgradeneeded", Upgrade)
}

但我的应用程序仍然死机退出!

fatal error: all goroutines are asleep - deadlock!
wasm_exec.js:51 
wasm_exec.js:51 goroutine 1 [chan receive]:
wasm_exec.js:51 main.main()
wasm_exec.js:51     /home/hajsf/idb/main.go:24 +0x4
wasm_exec.js:51 
wasm_exec.js:51 goroutine 6 [chan receive]:
wasm_exec.js:51 main.(*DataBase).init.func1({{}, 0x7ff8000100000011, 0x410240}, {0x40ec80, 0x1, 0x1})
wasm_exec.js:51     /home/hajsf/idb/initiate.go:57 +0xe
wasm_exec.js:51 syscall/js.handleEvent()
wasm_exec.js:51     /usr/local/go/src/syscall/js/func.go:96 +0x27
wasm_exec.js:51 
wasm_exec.js:51 goroutine 7 [select]:
wasm_exec.js:51 net/http.(*Transport).RoundTrip(0x324e20, 0x492000)
wasm_exec.js:51     /usr/local/go/src/net/http/roundtrip_js.go:170 +0x8d
wasm_exec.js:51 net/http.send(0x492000, {0xbe880, 0x324e20}, {0x0, 0x0, 0x0})
wasm_exec.js:51     /usr/local/go/src/net/http/client.go:252 +0x8b
wasm_exec.js:51 net/http.(*Client).send(0x334a80, 0x492000, {0x0, 0x0, 0x0})
wasm_exec.js:51     /usr/local/go/src/net/http/client.go:176 +0x11
wasm_exec.js:51 net/http.(*Client).do(0x334a80, 0x492000)
wasm_exec.js:51     /usr/local/go/src/net/http/client.go:725 +0xb5
wasm_exec.js:51 net/http.(*Client).Do(...)
wasm_exec.js:51     /usr/local/go/src/net/http/client.go:593
wasm_exec.js:51 net/http.(*Client).Get(0x334a80, {0x7546d, 0x1f})
wasm_exec.js:51     /usr/local/go/src/net/http/client.go:480 +0xe
wasm_exec.js:51 net/http.Get(...)
wasm_exec.js:51     /usr/local/go/src/net/http/client.go:449
wasm_exec.js:51 main.(*DataBase).init.func1.1(0x4360c0, {0x7546d, 0x1f})
wasm_exec.js:51     /home/hajsf/idb/initiate.go:43 +0x4
wasm_exec.js:51 created by main.(*DataBase).init.func1
wasm_exec.js:51     /home/hajsf/idb/initiate.go:40 +0xd
wasm_exec.js:151 exit code: 2
exit @ wasm_exec.js:151
runtime.wasmExit @ wasm_exec.js:275
$runtime.wasmExit @ main.wasm:0xe065d
$runtime.exit @ main.wasm:0xe048b
$runtime.fatalthrow.func1 @ main.wasm:0x7c1a2
$runtime.systemstack @ main.wasm:0xdd8f7
$runtime.fatalthrow @ main.wasm:0x7bff8
$runtime.throw @ main.wasm:0x7ba33
$runtime.checkdead @ main.wasm:0x9bcb8
$runtime.mput @ main.wasm:0x9e0f6
$runtime.stopm @ main.wasm:0x8ae91
$runtime.findrunnable @ main.wasm:0x8d33e
$runtime.schedule @ main.wasm:0x91430
$runtime.park_m @ main.wasm:0x9247f
$runtime.mcall @ main.wasm:0xdd88c
$runtime.gopark @ main.wasm:0x81740
$runtime.selectgo @ main.wasm:0xa5c4f
$net_http.__Transport_.RoundTrip @ main.wasm:0x3f3ae3
$wasm_pc_f_loop @ main.wasm:0xe0444
$wasm_export_resume @ main.wasm:0xe0425
_resume @ wasm_exec.js:588
(anonymous) @ wasm_exec.js:599
IndexedDB (async)
syscall/js.valueCall @ wasm_exec.js:399
$syscall_js.valueCall @ main.wasm:0x14799e
$syscall_js.Value.Call @ main.wasm:0x145065
$main.__DataBase_.init @ main.wasm:0x479c61
$main.init.0 @ main.wasm:0x47d181
$runtime.doInit @ main.wasm:0xa0e3d
$runtime.main @ main.wasm:0x80948
$wasm_pc_f_loop @ main.wasm:0xe0444
$wasm_export_run @ main.wasm:0xe0417
run @ wasm_exec.js:577
init @ wasm.js:7
await in init (async)
(anonymous) @ (index):20
(anonymous) @ (index):22
wasm_exec.js:586 Uncaught (in promise) Error: Go program has already exited
    at global.Go._resume (wasm_exec.js:586)
    at wasm_exec.js:599
_resume @ wasm_exec.js:586
(anonymous) @ wasm_exec.js:599
Promise.then (async)
syscall/js.valueCall @ wasm_exec.js:399
$syscall_js.valueCall @ main.wasm:0x14799e
$syscall_js.Value.Call @ main.wasm:0x145065
$net_http.__Transport_.RoundTrip @ main.wasm:0x3f3943
$wasm_pc_f_loop @ main.wasm:0xe0444
$wasm_export_resume @ main.wasm:0xe0425
_resume @ wasm_exec.js:588
(anonymous) @ wasm_exec.js:599
IndexedDB (async)
syscall/js.valueCall @ wasm_exec.js:399
$syscall_js.valueCall @ main.wasm:0x14799e
$syscall_js.Value.Call @ main.wasm:0x145065
$main.__DataBase_.init @ main.wasm:0x479c61
$main.init.0 @ main.wasm:0x47d181
$runtime.doInit @ main.wasm:0xa0e3d
$runtime.main @ main.wasm:0x80948
$wasm_pc_f_loop @ main.wasm:0xe0444
$wasm_export_run @ main.wasm:0xe0417
run @ wasm_exec.js:577
init @ wasm.js:7
await in init (async)
(anonymous) @ (index):20
(anonymous) @ (index):22
wasm_exec.js:586 Uncaught Error: Go program has already exited
    at global.Go._resume (wasm_exec.js:586)
    at IDBOpenDBRequest.<anonymous> (wasm_exec.js:599)

有什么想法吗?

我找到了,goroutine应该涵盖了完整的功能范围,比如:

js.FuncOf(func(this js.Value, args []js.Value) interface{} {
  go func() {
    [...]
    someBlockingFunction()
    [...]
  }()
})