原文在這里。
由 Johan Brandhorst-Satzkorn, Julien Fabre, Damian Gryski, Evan Phoenix, and Achille Roussel 發(fā)布于 2023年9月13日
Go 1.21添加了一個(gè)新的端口,通過(guò)新的GOOS值wasip1來(lái)定位WASI預(yù)覽1系統(tǒng)調(diào)用API。該端口建立在Go 1.11引入的現(xiàn)有WebAssembly端口的基礎(chǔ)上。
WebAssembly 是什么
WebAssembly(Wasm)是一種最初設(shè)計(jì)用于Web的二進(jìn)制指令格式。它代表了一個(gè)標(biāo)準(zhǔn),允許開(kāi)發(fā)人員在Web瀏覽器中以接近本機(jī)速度直接運(yùn)行高性能、低級(jí)別的代碼。
Go首次在1.11版本中添加了對(duì)編譯成Wasm的支持,通過(guò)js/wasm端口實(shí)現(xiàn)。這允許使用Go編譯器編譯的Go代碼在Web瀏覽器中執(zhí)行,但需要一個(gè)JavaScript執(zhí)行環(huán)境。
隨著Wasm的使用增加,除了在瀏覽器之外的用例也增多。許多云提供商現(xiàn)在提供服務(wù),允許用戶直接執(zhí)行Wasm可執(zhí)行文件,利用新的WebAssembly系統(tǒng)接口(WASI)系統(tǒng)調(diào)用API。
WebAssembly 系統(tǒng)接口
WASI定義了一個(gè)用于Wasm可執(zhí)行文件的系統(tǒng)調(diào)用API,允許它們與系統(tǒng)資源進(jìn)行交互,如文件系統(tǒng)、系統(tǒng)時(shí)鐘、隨機(jī)數(shù)據(jù)工具等等。WASI規(guī)范的最新版本被稱為wasi_snapshot_preview1,從中我們派生出了GOOS名稱wasip1。新版本的API正在開(kāi)發(fā)中,未來(lái)在Go編譯器中支持它們可能意味著添加一個(gè)新的GOOS。
WASI的創(chuàng)建使得許多Wasm運(yùn)行時(shí)(宿主)能夠圍繞其標(biāo)準(zhǔn)化它們的系統(tǒng)調(diào)用API。一些Wasm/WASI宿主的示例包括Wasmtime、Wazero、WasmEdge、Wasmer和NodeJS。還有許多云提供商提供Wasm/WASI可執(zhí)行文件的托管服務(wù)。
Go 中如何使用 WebAssembly
請(qǐng)確保已安裝至少1.21版本的Go。對(duì)于此演示,我們將使用Wasmtime主機(jī)來(lái)執(zhí)行我們的二進(jìn)制文件。讓我們從一個(gè)簡(jiǎn)單的 main.go
開(kāi)始:
package main
import "fmt"
func main() {
fmt.Println("Hello world!")
}
使用如下命令進(jìn)行編譯:
$ GOOS=wasip1 GOARCH=wasm go build -o main.wasm main.go
這將會(huì)生成一個(gè)名為 main.wasm
的文件,我們可以使用 wasmtime
執(zhí)行:
$ wasmtime main.wasm
Hello world!
這就是開(kāi)始使用Wasm/WASI所需的全部!幾乎所有Go的功能都可以在 wasip1
上正常工作。要了解有關(guān)WASI如何與Go一起工作的詳細(xì)信息,請(qǐng)參閱提案。
測(cè)試 wasip1
構(gòu)建和運(yùn)行二進(jìn)制文件很容易,但有時(shí)我們希望能夠直接運(yùn)行 go test
,而無(wú)需手動(dòng)構(gòu)建和執(zhí)行二進(jìn)制文件。與 js/wasm
端口類似,Go安裝中包含的標(biāo)準(zhǔn)庫(kù)分發(fā)版本附帶一個(gè)文件,使這個(gè)過(guò)程變得非常簡(jiǎn)單。在運(yùn)行Go測(cè)試時(shí),將 misc/wasm
目錄添加到 PATH
中,它將使用你選擇的Wasm主機(jī)來(lái)運(yùn)行測(cè)試。這是通過(guò) go test
在PATH中找到此文件時(shí)自動(dòng)執(zhí)行 misc/wasm/go_wasip1_wasm_exec
來(lái)實(shí)現(xiàn)的:
$ export PATH=$PATH:$(go env GOROOT)/misc/wasm
$ GOOS=wasip1 GOARCH=wasm go test ./...
這將使用 Wasmtime
運(yùn)行 go test
??梢允褂铆h(huán)境變量 GOWASIRUNTIME
來(lái)控制所使用的Wasm主機(jī)。目前支持的變量值包括 wazero
、wasmedge
、wasmtime
和 wasmer
。請(qǐng)注意,Go wasip1
二進(jìn)制文件在所有主機(jī)上尚不能完美執(zhí)行(參見(jiàn)#59907和#60097)。
也可以使用 go run
來(lái)執(zhí)行上面的程序:
$ GOOS=wasip1 GOARCH=wasm go run ./main.go
Hello world!
使用go:wasmimport在Go中包裝Wasm函數(shù)
除了新的 wasip1/wasm
端口外,Go 1.21還引入了一個(gè)新的編譯器指令:go:wasmimport
。它指示編譯器將對(duì)帶有注釋的函數(shù)的調(diào)用轉(zhuǎn)換為對(duì)由主機(jī)模塊名稱和函數(shù)名稱指定的函數(shù)的調(diào)用。這個(gè)新的編譯器功能允許我們?cè)贕o中定義wasip1系統(tǒng)調(diào)用API,以支持新的端口,但它不限于在標(biāo)準(zhǔn)庫(kù)中使用。
例如,wasip1系統(tǒng)調(diào)用API定義了 random_get
函數(shù),并通過(guò)runtime包中定義的函數(shù)包裝器暴露給Go標(biāo)準(zhǔn)庫(kù)。它看起來(lái)像這樣:
//go:wasmimport wasi_snapshot_preview1 random_get
//go:noescape
func random_get(buf unsafe.Pointer, bufLen size) errno
然后,將這個(gè)函數(shù)包裝器包裝在標(biāo)準(zhǔn)庫(kù)中供使用的更人性化的函數(shù)中:
func getRandomData(r []byte) {
if random_get(unsafe.Pointer(&r[0]), size(len(r))) != 0 {
throw("random_get failed")
}
}
這樣,用戶可以使用字節(jié)切片調(diào)用 getRandomData
,并最終將其傳遞給主機(jī)定義的 random_get
函數(shù)。同樣,用戶可以為主機(jī)函數(shù)定義自己的包裝器。
要了解如何在Go中包裝Wasm函數(shù)的復(fù)雜性的更多細(xì)節(jié),請(qǐng)參閱go:wasmimport提案。
局限性
雖然wasip1端口通過(guò)了所有標(biāo)準(zhǔn)庫(kù)測(cè)試,但Wasm架構(gòu)有一些顯著的基本限制,可能會(huì)讓用戶感到驚訝。
Wasm是一個(gè)沒(méi)有并行性的單線程架構(gòu)。調(diào)度器仍然可以調(diào)度goroutine以并發(fā)運(yùn)行,標(biāo)準(zhǔn)輸入/輸出/錯(cuò)誤是非阻塞的,因此一個(gè)goroutine可以在另一個(gè)讀取或?qū)懭霑r(shí)執(zhí)行,但是任何主機(jī)函數(shù)調(diào)用(例如使用上面的示例請(qǐng)求隨機(jī)數(shù)據(jù))都會(huì)導(dǎo)致所有g(shù)oroutine阻塞,直到主機(jī)函數(shù)調(diào)用返回。
wasip1 API中一個(gè)顯著缺失的功能是完整的網(wǎng)絡(luò)套接字實(shí)現(xiàn)。wasip1只定義了對(duì)已經(jīng)打開(kāi)的套接字進(jìn)行操作的函數(shù),這使得無(wú)法支持Go標(biāo)準(zhǔn)庫(kù)的一些最流行的功能,如HTTP服務(wù)器。像Wasmer和WasmEdge這樣的主機(jī)實(shí)現(xiàn)了wasip1 API的擴(kuò)展,允許打開(kāi)網(wǎng)絡(luò)套接字。盡管Go編譯器沒(méi)有實(shí)現(xiàn)這些擴(kuò)展,但存在第三方庫(kù),github.com/stealthrocket/net,使用go:wasmimport允許在支持的Wasm主機(jī)上使用net.Dial和net.Listen。這允許在使用此包時(shí)創(chuàng)建net/http服務(wù)器和其他與網(wǎng)絡(luò)相關(guān)的功能。
Go中的Wasm的未來(lái)
wasip1/wasm
端口的添加只是我們希望引入Go的Wasm功能的開(kāi)端。請(qǐng)密切關(guān)注問(wèn)題跟蹤器,了解有關(guān)將Go函數(shù)導(dǎo)出到Wasm(go:wasmexport)、32位端口和未來(lái)WASI API兼容性的提案。
參與其中
如果你正在嘗試并希望為Wasm和Go做出貢獻(xiàn),請(qǐng)參與其中!Go問(wèn)題跟蹤器跟蹤所有正在進(jìn)行的工作,Gophers Slack上的 #webassembly 頻道是討論Go和WebAssembly的好地方。我們期待聽(tīng)到你的聲音!文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-709798.html

聲明:本作品采用署名-非商業(yè)性使用-相同方式共享 4.0 國(guó)際 (CC BY-NC-SA 4.0)進(jìn)行許可,使用時(shí)請(qǐng)注明出處。
Author: mengbin
blog: mengbin
Github: mengbin92
cnblogs: 戀水無(wú)意文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-709798.html
到了這里,關(guān)于WASI support in Go的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!