Golang中Webassembly报错:userCurrent未定义问题
Golang中Webassembly报错:userCurrent未定义问题 我正在尝试使用 WebAssembly。但在编译时遇到了一个错误:
GOOS=js GOARCH=wasm go build -o main.wasm # github.com/lib/pq ../../github.com/lib/pq/conn.go:321:13: undefined: userCurrent
有人知道这是什么问题以及如何解决吗?
skillian:
我不认为它的目标是消除对Web服务器的需求。
如果我的理解正确,Web服务器是将wasm上传到客户端吗?那么SQL相关的操作是在哪里以及如何完成的?是在Web服务器端还是在浏览器中?
更多关于Golang中Webassembly报错:userCurrent未定义问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
我刚刚检查了 github.com/lib/pq/conn.go 的第 321 行,没有看到任何对 userCurrent 的引用。你能 go get 那个包然后再试一次吗?
你不能直接从命令行运行 WebAssembly 模块。WebAssembly 模块是在网页浏览器中客户端运行的。你需要一个网页,通过类似以下代码将你的模块加载到浏览器中:
WebAssembly.instantiateStreaming(fetch('main.wasm'), importObject) // ...
然后,你就可以从运行在浏览器中的 JavaScript 引用你的 main.wasm 模块中暴露的函数。
Sibert:
我注释掉了 lib/pq(如果我正在使用 sqlx,还需要 lib/pq 吗?)
lib/pq 是 PostgreSQL 数据库驱动程序。没有它,你将无法使用 PostgreSQL 数据库。
Sibert:
但我无法在 Mac 上启动可执行文件。
如果你只想在你的 Mac 上运行它,为什么要构建一个 Wasm 模块呢?为什么不直接构建适用于 Mac 的版本呢?
skillian:
你的
main.wasm文件需要像其他 JavaScript 脚本一样,对你的 Web 应用程序是可访问的。
感谢你的回答。看来我并没有完全理解 wasm 的概念。
我原本的理解是 wasm 就像应用程序一样在浏览器中运行。但我还需要一个服务器吗?哪些部分应该在服务器上,哪些部分应该在浏览器中?
目前关于 wasm 的例子很少,我测试过的所有例子加载时间都很长,但运行起来更像一个桌面应用程序。
skillian:
您必须修改 lib/pq 的源代码,使其不再需要那个
userCurrent函数。
我注释掉了 lib/pq(如果我正在使用 sqlx,还需要 lib/pq 吗?),然后 go build 成功了。但我无法在 Mac 上启动可执行文件。我哪里做错了?
$ GOOS=js GOARCH=wasm go build -o main.wasm
$ ./main.wasm
-bash: ./main.wasm: cannot execute binary file
skillian:
你能先
go get那个包然后再试一次吗?
没有区别。还有其他建议吗?
$ GOOS=js GOARCH=wasm go build -o main.wasm # github.com/lib/pq
../../github.com/lib/pq/conn.go:321:13: undefined: userCurrent
$ go get github.com/lib/pq
$ GOOS=js GOARCH=wasm go build -o main.wasm # github.com/lib/pq
../../github.com/lib/pq/conn.go:321:13: undefined: userCurrent
skillian:
WebAssembly.instantiateStreaming(fetch(‘main.wasm’), importObject)
这个方法不起作用。浏览器怎么知道 main.wasm 在哪里?
skillian:
lib/pq 是 Postgres SQL 数据库驱动。没有它,你就无法使用 Postgres 数据库。
那么问题一定是 lib/pq 损坏了或者没有更新?
skillian:
如果你只是想在你的 Mac 上运行,为什么要构建一个 Wasm 模块?为什么不直接为 Mac 构建呢?
我正在研究这个网站
http://94.237.92.101:3030/mytopics
在使用 WebAssembly 时可能的外观和感觉。但看起来 Go 语言在这方面还没有准备好投入生产环境?
好的,如果我使用 git blame 查看 conn.go 文件,并回溯到最后一次修改第 321 行的提交(提交 cd7087504b4639a9b67e108f365062ab26335e8b),当我向上滚动查看时,会发现第 321 行现在包含了一个对 userCurrent 函数的调用。我建议使用 GitHub 上的最新代码进行更新,因为你手上的代码似乎有些过时了。
无论如何,如果我查看这个函数是在哪里定义的,会发现有一个 user_posix.go 和一个 user_windows.go 文件。这两个文件的构建约束都不适用于 Wasm,因此在为 Wasm 构建时,这个函数就没有被定义。你需要修改 lib/pq 的源代码,要么让它不再需要这个 userCurrent 函数,要么自己为 wasm 实现它。
这个错误是因为 lib/pq 包在编译到 WebAssembly 时调用了 user.Current() 函数,而该函数在 wasm 环境中不可用。os/user 包在 wasm 目标平台下没有完整的实现。
解决方案:
-
使用构建标签排除
lib/pq包(推荐): 由于 WebAssembly 通常在浏览器中运行,而数据库连接一般在后端服务器,你可能需要将前端(wasm)和后端代码分离。// 在你的 wasm 入口文件添加构建标签 //go:build wasm // +build wasm package main // 避免导入 lib/pq -
如果必须在 wasm 中使用数据库连接,可以尝试使用纯 Go 的数据库驱动,如
modernc.org/sqlite(适用于 SQLite):import ( _ "modernc.org/sqlite" "database/sql" ) func main() { db, err := sql.Open("sqlite", "file::memory:") // ... 使用数据库 } -
为
lib/pq创建 wasm 兼容的补丁(临时方案): 在项目中创建补丁文件覆盖userCurrent函数:// 在编译前替换或修改 lib/pq 的 conn.go 文件 // 将 userCurrent 函数替换为返回空值的实现 func userCurrent() (string, error) { return "", nil }
示例:分离前端代码的构建方式:
// main_wasm.go
//go:build wasm
// +build wasm
package main
import "syscall/js"
func main() {
// 纯前端逻辑,不导入数据库相关包
js.Global().Set("goFunc", js.FuncOf(jsCallback))
<-make(chan bool)
}
// main_server.go
//go:build !wasm
// +build !wasm
package main
import (
"database/sql"
_ "github.com/lib/pq"
)
func main() {
// 后端服务器逻辑,正常使用 lib/pq
db, _ := sql.Open("postgres", "user=postgres dbname=test")
defer db.Close()
}
编译命令保持不变:
GOOS=js GOARCH=wasm go build -o main.wasm
这样就能避免 wasm 编译时对 user.Current() 的依赖。


