Golang中为什么syscall/js包可以实现WebAssembly与DOM交互

Golang中为什么syscall/js包可以实现WebAssembly与DOM交互 我在多个网站上读到,WebAssembly 不能用于与 DOM 交互,但如果我没有理解错,在 Go 程序中编译为 WebAssembly 的 syscall/js可以与 DOM 交互。

或者,这里的“交互”是什么意思?

4 回复

等一下,你是说如果我组织得当,就可以绕过JavaScript,完全用Go来编程吗?

更多关于Golang中为什么syscall/js包可以实现WebAssembly与DOM交互的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


你好,

我对WebAssembly了解不深,但这个问题似乎解释了你的观察。

这个问题是关于需要一个垃圾收集器,以便能够从WebAssembly代码中直接访问DOM。如果没有这个功能,WASM代码就需要通过调用JavaScript来处理DOM操作,绕个弯子。

我猜这就是syscall/js为编译成WebAssembly的Go代码所做的事情。

// 代码示例:使用 syscall/js 调用 JavaScript
func main() {
    // 通过 js.Global() 访问全局对象,例如调用 alert
    js.Global().Call("alert", "Hello from Go WASM!")
}

是的,但对于大多数情况来说,这可能带来的麻烦多于其价值。以下是一份关于 Go WebAssembly + React 的指南:

WebAssembly with Go: Taking Web Apps to the Next Level

WebAssembly with Go: Taking Web Apps to the Next Level

这篇教程文章演示了我们如何将 WebAssembly (WASM) 与 Golang 集成,并在我们的开源项目中使用它,以简化功能并提供更丰富的用户体验。

我在实际环境中看到的大多数真正的用例,是人们希望在服务器和客户端之间共享逻辑。一个常见的例子是验证。你需要在服务器端进行验证,但通常你也希望在客户端和服务器端运行相同的验证逻辑,因此我见过一些团队将 wasm 分发到客户端。

在 Go 语言中,syscall/js 包确实允许编译为 WebAssembly 的 Go 程序与 DOM 交互。这里的“交互”指的是 Go 代码能够调用 JavaScript 函数、操作 DOM 元素、处理事件等。这通过 WebAssembly 的 JavaScript API 实现,具体来说,Go 的 WebAssembly 输出会与一个 JavaScript “胶水”代码一起运行,该代码在 Go 运行时和浏览器环境之间架起桥梁。

当 Go 代码编译为 WebAssembly 时,syscall/js 包提供了对 JavaScript 值和函数的包装。它使用 syscall/js 中的函数(如 js.Global() 获取全局对象)来间接调用 JavaScript API,从而操作 DOM。例如,你可以通过 js.Global().Get("document").Call("getElementById", "myElement") 来获取 DOM 元素。这本质上是通过 WebAssembly 的 import/export 机制与宿主环境(浏览器)通信。

以下是一个简单示例,展示如何使用 syscall/js 包在 Go 中修改 DOM 元素的内容:

package main

import (
    "syscall/js"
)

func main() {
    // 获取 document 对象
    doc := js.Global().Get("document")
    // 通过 ID 获取元素
    element := doc.Call("getElementById", "myDiv")
    // 设置元素内容
    element.Set("innerHTML", "Hello from Go WebAssembly!")
    
    // 保持 Go 程序运行,以便与 DOM 持续交互
    select {}
}

在这个例子中,Go 代码编译为 WebAssembly 后,在浏览器中运行时,会查找 ID 为 myDiv 的 DOM 元素并更新其内容。这之所以可行,是因为 Go 的 WebAssembly 模块通过 syscall/js 包导出了对 JavaScript 的调用,而浏览器中的 JavaScript 胶水代码处理这些调用并实际执行 DOM 操作。

因此,当人们说“WebAssembly 不能直接与 DOM 交互”时,他们指的是 WebAssembly 模块本身不包含 DOM API;它必须通过 JavaScript 中介来访问。Go 的 syscall/js 包正是提供了这种中介的抽象层,使得 Go 代码能够间接但有效地与 DOM 交互。

回到顶部