发布于 2026-01-06 4 阅读
0

使用 React 和 Go 创建 WebAssembly 应用 WASM、React 和 Go 入门

使用 React 和 Go 创建一个 WebAssembly 应用

WASM、React 和 Go 入门

WASM、React 和 Go 入门

WebAssembly 很棒——这几乎算不上什么新闻,但是如何将它与 React 和 Go 结合使用呢?说实话,网上有很多不错的资料可以帮助你解决这个问题。但就我个人而言,体验并不流畅。我想要的是一篇简洁明了、内容最新的文章。首先,我想要的是一个使用 Create-React-App 的解决方案,因为谁想折腾 Webpack 呢?🙃🙃

本简短教程旨在向您展示我是如何将所有组件整合在一起,并最终编译并运行一个基于 React 的 Go 程序到 WebAssembly 的环境中的。我假设您已具备以下条件:

  • 您已安装 Go 语言(1.11 及以上版本)。
  • npm/Yarn 已安装。

那么,让我们开始吧。

在本教程中,我们将向 React 的输入框中输入一个值,然后使用 WebAssembly 来渲染该值。简单又有趣,对吧?

替代文字

克隆此仓库该仓库包含已分离的应用。我尽量使这篇文章简洁明了,因此可能会(无意中)遗漏一些内容。

根目录中包含main.go以下代码:

package main

import (
    "fmt"
    "syscall/js"
)

var c chan bool

// init is called even before main is called. This ensures that as soon as our WebAssembly module is ready in the browser, it runs and prints "Hello, webAssembly!" to the console. It then proceeds to create a new channel. The aim of this channel is to keep our Go app running until we tell it to abort.
func init() {
    fmt.Println("Hello, WebAssembly!")
    c = make(chan bool)
}

func main() {
    // here, we are simply declaring the our function `sayHelloJS` as a global JS function. That means we can call it just like any other JS function.
    js.Global().Set("sayHelloJS", js.FuncOf(SayHello))
    println("Done.. done.. done...")

    // tells the channel we created in init() to "stop".
    <-c
}

// SayHello simply set the textContent of our element based on the value it receives (i.e the value from the input box)
// the element MUST exist else it'd throw an exception
func SayHello(jsV js.Value, inputs []js.Value) interface{} {
    message := inputs[0].String()
    h := js.Global().Get("document").Call("getElementById", "message")
    h.Set("textContent", message)
    return nil
}
Enter fullscreen mode Exit fullscreen mode

我们的 `sayHello` 函数接受两个参数。我们更关注第二个参数。第二个参数本质上是一个 `js.Value` 数组。这是因为我们可以从 JavaScript 传递任意数量的参数。要获取这些值,我们只需使用索引即可。所以,在本例中,我们想要获取输入框中输入的值。

message := inputs[0].String()
Enter fullscreen mode Exit fullscreen mode

就像我之前说的,我们使用数组的索引来获取我们想要的任何值。

h := js.Global().Get("document").Call("getElementById", "message")
h.Set("textContent", message)
Enter fullscreen mode Exit fullscreen mode

以上代码类似于:

let h = document.getElementById("message")
h.textContent = message
Enter fullscreen mode Exit fullscreen mode

所以我们现在要做的就是将 id 为“message”的元素的文本更改为输入值。

运行以下命令进行编译main.go

GOOS=js GOARCH=wasm go build -o ../client/public/main.wasm
Enter fullscreen mode Exit fullscreen mode

客户方面

App.js在componentDidMount()中,我们有以下代码:

async componentDidMount() {
    let { instance, module } = await WebAssembly.instantiateStreaming(fetch("main.wasm"), window.go.importObject)
    await window.go.run(instance)
    this.setState({
      mod: module,
      inst: instance
    })
  }
Enter fullscreen mode Exit fullscreen mode

我们正在实例化main.wasm并运行我们的 WASM 函数。这意味着我们现在可以继续在应用中调用 WASM 函数了。同时,我们也设置了模块和实例的​​状态,以备后用。此外,你会注意到我们正在执行 `go()` 操作window.go.run(instance)它是从哪里来的呢?其实,它在 React 应用中已经处理好了。你会注意到有一个wasmjs文件夹,其中包含一个 ` init_jsgo.js` 文件。这个wasm_exec.js文件以及使用 WASM 文件和 JS 所需的其他文件都已使用 webpack 创建并打包到我们的 React 应用中。因此,它将 `go()` 实例绑定到全局 `window` 对象。所以,它不再声明一个新的 `go()` 实例,而是作为 `window` 对象变量存在。

 handleSubmit = async (e) => {
    e.preventDefault()
    window.sayHelloJS(this.state.message)
  }
Enter fullscreen mode Exit fullscreen mode

这是我们调用之前在 Go 代码中注册的函数 sayHelloJS!注意我们将其作为 window 对象的属性来访问。这是因为我们是从 React 中调用它的。如果我们直接调用它,它将是 undefined sayHelloJS

<span id="message">
    Ayomide Onigbinde wrote this!!😉...💕 from WebAssembly and Golang
</span>
Enter fullscreen mode Exit fullscreen mode

我们有这样一个 HTML 元素。请注意,它的 id 是“message”。这个元素就是我们在 Go 代码中操作的,而 Go 代码最终被编译成了 WebAssembly!所以这个元素必须存在,否则就会抛出异常。它会根据我们在输入框中输入的值而改变!这一切都是由 WebAssembly(由 Go 编译而来)实现的!🎉🎉

我已经尽力解释了!如果还有什么不清楚的地方,请留言,我们一起来弄明白😉😉。

非常感谢 Aaron 的教程,也特别感谢LogRocket 的 Chris,这对我帮助太大了!这篇 Dev.to 的文章也让我更好地理解了 React 与 WASM 的结合使用。

文章来源:https://dev.to/oayomide/create-a-web assembly-app-with-react-and-go-39j7