golang 安裝
通過 官方地址 下載。MacOS 也可通過 brew
快速安裝:
$ brew install golang
$ go version
go version go1.17.2 darwin/arm64
golang 環境測試
新建檔案 main.go
,寫入:
package main
import "fmt"
func main() {
fmt.Println("Hello World!")
}
執行 go run main.go
,將輸出:
$ go run main.go
Hello World!
如果啟用了GO MODULES
,則需要使用go mode init
初始化模組,或設定GO111MODULE=auto
。
將 golang 打包為 WASM
通常有兩種打包方式,一種是 golang 自帶的,另外是使用 tinygo
。推薦使用 tinygo
,因為編譯出的 wasm 模組更小。
使用 golang 原生編譯
在編譯
wasm
模組前,需要設定 golang 交叉編譯引數,目標系統GOOS=js
和目標架構GOARCH=wasm
,編譯 wasm 模組:// macos $ GOOS=js GOARCH=wasm go build -o main.wasm // windows 臨時設定 golang 環境引數(僅作用於當前CMD) $ set GOOS=js $ set GOARCH=wasm $ go build -o main.wasm
使用 tinygo 編譯
直接按照官方文件安裝即可,MacOS 如下:
$ brew tap tinygo-org/tools $ brew install tinygo $ tinygo version tinygo version 0.20.0 darwin/amd64 (using go version go1.17.2 and LLVM version 11.0.0)
使用以下命令對
main.go
再次進行打包:$ tinygo build -o main-tiny.wasm
打包檔案大小對比
$ du -sh ./*.wasm 228K ./main-tiny.wasm 1.9M ./main.wasm
在瀏覽器中跑起來
要想在瀏覽器中跑 main.wasm
,首先需要 JS 膠水程式碼,golang 已經為我們提供了,直接複製過來。需要注意的是,使用 tinygo
和 原生編譯的膠水程式碼是有差異的,根據具體情況拷貝對應的:
// 原生編譯
$ cp "$(go env GOROOT)/misc/wasm/wasm_exec.js" .
// tinygo編譯
$ cp "$(tinygo env TINYGOROOT)/targets/wasm_exec.js" ./wasm_exec_tiny.js
其次,需要一個 HTML
入口檔案,建立 index.html
檔案,並寫入以下程式碼:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="./wasm_exec_tiny.js"></script>
</head>
<body>
<script>
const go = new Go(); // wasm_exec.js 中的定義
WebAssembly.instantiateStreaming(fetch('./main-tiny.wasm'), go.importObject)
.then(res => {
go.run(res.instance); // 執行 go main 方法
});
</script>
</body>
</html>
最後,起一個 http server 讓它跑起來吧~
// python
$ python3 -m http.server
$ python2 -m SimpleHTTPServer
// node
$ npm i -g http-server
$ hs
// gp
$ go get -u github.com/shurcooL/goexec
$ goexec 'http.ListenAndServe(`:8080`, http.FileServer(http.Dir(`.`)))'
異常記錄
通過 node 的 http-server 起的服務,載入會報錯:
> TypeError: Failed to execute 'compile' on 'WebAssembly': Incorrect response MIME type. Expected 'application/wasm'.
原因是 wasm 檔案響應頭的 content-type 為
application/wasm; charset=utf-8
,應該為application/wasm
。已知的解決方法為修改 HTML 中 wasm 的初始化方式為:fetch('./main-tiny.wasm') .then(res => res.arrayBuffer()) .then(buffer => { WebAssembly.instantiate(buffer, go.importObject) .then(res => { go.run(res.instance); }) })