一分鐘搞明白!快速掌握 Go WebAssembly
來源:腦子進煎魚了
最近因為各種奇怪的原因,更多的接觸到了 WebAssembly。雖然之前很多部落格也翻過寫過各種文章,但總感覺欠些味道。於是今天梳理了一版,和大家一起展開學習。
先來一張經典圖:
WebAssembly 是什麼
以下是 Mozilla 在 MDN 上給出的定義:
WebAssembly(縮寫:Wasm)是一種新的編碼方式,可以在現代的網路瀏覽器中執行 - 它是一種低階的類組合語言,具有緊湊的二進位制格式,可以接近原生的效能執行,併為諸如 C/C++ 等語言提供一個編譯目標,以便它們可以在 Web 上執行。它也被設計為可以與 JavaScript 共存,允許兩者一起工作。
Wasm 官網自己挑出的重點是:
是一種基於堆疊的虛擬機器的二進位制指令格式。 被設計為程式語言的可移植編譯目標。 能夠在網路上部署客戶端和伺服器應用程式。
新編碼方式,可以在瀏覽器中執行。可以以接近原生的效能執行。可以跨語言,例如:C/C++;可以與 JavaScript 共存。
看著是一個不錯的可跨平臺執行的新玩具。
由哪家研發
最早 WebAssembly1.0 基於 asm.js(Javascript 的嚴格子集,靜態型別,取消垃圾回收機制等)的特性集實現。隨後的 WebAssembly2.0 又根據新的標準進行了進一步的延伸和開發。
WebAssembly 的開發團隊分別來自 Mozilla、Google、Microsoft、Apple,代表著四大網路瀏覽器 Firefox、Chrome、Microsoft Edge、Safari。
一些重要的時間線:
2015 年 WebAssembly 首次釋出,在上述四大瀏覽器中進行了 Unity 的 Angry Bots(憤怒的機器人)的演示。 2017 年 3 月,首次釋出 WebAssembly MVP 版本,預覽版本結束,正式進行釋出,可以理解為 1.0。 2018 年 2 月,WebAssembly 工作組(WebAssembly Working Group)釋出了核心規範、JavaScript 介面和 Web API 的三個公開工作草案。 2019 年,Chrome 75 釋出,預設啟用 WebAssembly 執行緒。 2022 年 6 月,開始釋出 WebAssembly 2.0。
幾家大廠派人一起做的,比較新,近幾年才開始更多的被支援。當前還在 WebAssembly 2.0 的階段,還在發展階段。
1.0 和 2.0 區別之一
直觀上來看,1.0 和 2.0 最大的區別在於:
1.0 主要目標是在所有主要瀏覽器中能執行 WebAssembly。根據統一截至 2022 年 10 月 ,96% 的已安裝瀏覽器支援 WebAssembly(1.0 版),基本實現了全覆蓋。 讓 WebAssembly 煥發第二春(2.0)的:可以藉助 WASI(WebAssembly System Interfac) 的模組化系統介面,能夠藉此中間產物 .wasm 實現各語言的集合和互相整合。
WebAssembly 2.0 起,邊界更大了,目標完全就是可移植、安全的高階語言。期望應用於瀏覽器、各程式語言、各系統中。
大有一個 JVM 的感覺:
Go 快速上手
在我們快速瞭解了 WebAssembly 的背景後。我們落到實處,看看 Go 語言的 WebAssembly 情況如何,又是如何使用。
Go 目前有兩種使用 WebAssembly 的方式,第一種是使用 syscall/js
標準庫,四捨五入算勉強支援了 WebAssembly 1.0。
程式碼如下:
package main
import "syscall/js"
func main() {
alert := js.Global().Get("alert")
alert.Invoke("腦子進煎魚了!")
}
編譯命令:
$ GOOS=js GOARCH=wasm go build -o jianyu.wasm
再使用 JS 中對應 WebAssembly 的呼叫就可以了。
第二種使用方式,是使用開源庫 tinygo-org/tinygo[1],其基於 LLM,支援了 WebAssembly1.0/2.0 (WASM/WASI)。
tinygo brew 安裝方式:
$ brew tap tinygo-org/tools
$ brew install tinygo
如果安裝成功,執行 tinygo version
就可以看到版本資訊。
Go wasm 程式碼如下:
import (
figure "github.com/common-nighthawk/go-figure"
)
//export HelloWorld
func HelloWorld() {
myFigure := figure.NewFigure("Hello World", "", true)
myFigure.Print()
}
func main() {}
編譯命令:
tinygo build -o module.wasm -target wasi .
執行成功後,將會在對應目錄編譯出 module.wasm 二進位制檔案,可以由其他的平臺、語言進行使用。
如果你希望在 Go 或其他語言中呼叫所生成的 .wasm,需要找到對應符合 WASI 的庫和規則。
下面是 Go wasmer-go 呼叫 .wasm 的程式碼:
import (
"fmt"
"io/ioutil"
wasmer "github.com/wasmerio/wasmer-go/wasmer"
)
func main() {
wasmBytes, _ := ioutil.ReadFile("module.wasm")
store := wasmer.NewStore(wasmer.NewEngine())
module, _ := wasmer.NewModule(store, wasmBytes)
wasiEnv, _ := wasmer.NewWasiStateBuilder("wasi-program").
// Choose according to your actual situation
// Argument("--foo").
// Environment("ABC", "DEF").
// MapDirectory("./", ".").
Finalize()
importObject, err := wasiEnv.GenerateImportObject(store, module)
check(err)
instance, err := wasmer.NewInstance(module, importObject)
check(err)
start, err := instance.Exports.GetWasiStartFunction()
check(err)
start()
HelloWorld, err := instance.Exports.GetFunction("HelloWorld")
check(err)
result, _ := HelloWorld()
fmt.Println(result)
}
func check(e error) {
if e != nil {
panic(e)
}
}
執行成功後會輸出 “Hello World”。
Go 標準庫 syscall/js
標準庫只支援 WebAssembly1.0,只能應用於 JS 相關的場景,並不能被其他語言所整合。
其中 tinygo 實現了 WASI,藉助 WASI 這一標準介面與其他平臺語言互相整合。但 tinygo 並沒有支援所有的 Go 語法特性,具體可以檢視 Go language features[2]。
這塊需要特別注意,不同語言對 WebAssembly(WASI)的支援程度均不一樣。
其他應用場景
帶火 WebAssembly 的還有一個重要的因素,那就是在各種雲原生的元件上都可以整合和使用,進一步延伸了場景。
例如在 Envoy 和 Istio 上,可以使用 wasm 很方便的將自定義 filter 整合到 Envoy 中,實現 Envoy 代理的功能增強。
總結
今天我們快速的對 WebAssembly 進行了背景瞭解、Go 快速上手、擴充套件場景瞭解等。雖然 WebAssembly 是一個新輪子,也號稱可以藉助 WASI 整合和被整合。
但實際上現在各語言對 WebAssembly 的支援程度都不一樣,像 Go 官方自己提供的標準庫就維護的不怎麼樣,WASI 的 issues 也沒有繼續推進。
甚至在其他語言的互通,現在仍然有著或多或少會導致阻塞無法應用的問題。可能,還需要再過個 3~5 年?
但如此多語言的庫維護,能否長久的迭代和維護。也是一個更大的問題。
參考資料
tinygo-org/tinygo:
[2]Go language features:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70024923/viewspace-2941743/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 只需一分鐘,帶你快速掌握linux head命令!Linux
- 分分鐘掌握快速排序排序
- 一分鐘明白MySQL聚簇索引和非聚簇索引MySql索引
- 快速掌握 Go 工作區模式Go模式
- YUI TreeView搞明白了UIView
- 一分鐘掌握MySQL的InnoDB引擎B+樹索引MySql索引
- 一分鐘教程-超橢圓快速繪製
- 一分鐘sed入門(一分鐘系列)
- 20分鐘上手 webAssemblyWeb
- 【長文】帶你搞明白RedisRedis
- 無門檻一分鐘掌握的設計工具,電商設計利器!
- ETL都沒弄懂,談什麼大資料 ?我用一分鐘給你整明白大資料
- 線上主圖設計工具,一分鐘快速上手使用模板!
- APISpace 的 ChatGPT 它來了!一分鐘快速接入沒煩惱APIChatGPT
- Linux 使用者必知:一分鐘掌握14個常用Linux命令列快捷鍵Linux命令列
- 效能測試手冊:一分鐘掌握LoadRunner關聯函式應該放在那函式
- 兩分鐘帶你快速掌握Flutter的路由與導航Flutter路由
- 5 分鐘教你快速掌握 GitHub Actions 自動部署部落格Github
- 一篇文章搞明白CORS跨域CORS跨域
- Go1.11要支援 WebAssembly 了GoWeb
- 一分鐘玩轉 Spring IoC!Spring
- 一分鐘玩轉 Spring IoCSpring
- 搞明白這四個問題Linux就好學多了Linux
- 五分鐘用 Docker 快速搭建 Go 開發環境DockerGo開發環境
- 快速掌握keepalived
- 第 55 期 Go&WebAssembly 簡介GoWeb
- 一分鐘學會《模板方法模式》模式
- 一分鐘開啟Tomcat https支援TomcatHTTP
- 一分鐘學習Markdown語法
- 一分鐘瞭解PON網路
- 一分鐘瞭解JAVA語言Java
- python遞迴(一分鐘讀懂)Python遞迴
- Flask一分鐘Mock一個APIFlaskMockAPI
- 這一次,徹底幫你搞明白 ImageView ScaleTypeView
- 從業八年才搞明白“留存”的本質。
- 防禦DDoS原理搞明白,防禦效果才能事半功倍
- Mybatis動態對映,這次終於搞明白了MyBatis
- 十分鐘快速掌握HashMap底層實現原理(圖文詳解)HashMap