Slide 1

Slide 1 text

Go1.21とWebAssembly Oct 13 2023 1

Slide 2

Slide 2 text

Name = Asuka(あすか) SNS = { 𝕏 = @a_skua } Career = { …Nov = PHP & Go Dec… = TypeScript } PR = 技術書典15にサークル参加します(WASI本を予定) [Profile] 2

Slide 3

Slide 3 text

Go 1.21 is released! - The Go Programming Language A new port to WASI Go 1.21 adds an experimental port for WebAssembly System Interface (WASI), Preview 1 (GOOS=wasip1, GOARCH=wasm). To facilitate writing more general WebAssembly (Wasm) code, the compiler also supports a new directive for importing functions from the Wasm host: go:wasmimport. WASIのプレビュー1をサポートしたよ! と盛り上がっていた(主観) 3

Slide 4

Slide 4 text

Go 1.21 is released! - The Go Programming Language A new port to WASI Go 1.21 adds an experimental port for WebAssembly System Interface (WASI), Preview 1 (GOOS=wasip1, GOARCH=wasm). To facilitate writing more general WebAssembly (Wasm) code, the compiler also supports a new directive for importing functions from the Wasm host: go:wasmimport. ʕ◔ϖ◔ʔ !? 4

Slide 5

Slide 5 text

どういう書き方ができるようになる? 5

Slide 6

Slide 6 text

6 package main import ( "syscall/js" ) func count(n int32) { js.Global().Call("count", n); } func main() { for i := int32(0); i < 10; i++ { count(i) } } package main //go:wasmimport env count func count(int32) func main() { for i := int32(0); i < 10; i++ { count(i) } }

Slide 7

Slide 7 text

7 import "./wasm_exec.js"; const go = new Go(); const module = await WebAssembly.compileStreaming(fetch("main.wasm")).catch((err) => { console.error(err); }); window.count = (n) => { console.log(n); } window.run = async function() { console.clear(); await go.run(await WebAssembly.instantiate(module, go.importObject)); };

Slide 8

Slide 8 text

8 〜省略〜 const count = (n) => { console.log(n); } window.run = async function() { console.clear(); await go.run(await WebAssembly.instantiate(module, { env: { count, }, ...go.importObject, })); };

Slide 9

Slide 9 text

9 どういう書き方ができるようになる? 1. Wasmのインポートを構文として直接表現できるようになった. 2. JS(など)のコードをGoからアクセスするためにグローバルに展開しなくとも良くなっ た.

Slide 10

Slide 10 text

10 課題感 Stringとかまだ直接扱えない. Go value Wasm value int32, uint32 i32 int64, uint64 i64 float32 f32 float64 f64 unsafe.Pointer i32

Slide 11

Slide 11 text

11 課題感 Stringとかまだ直接扱えない. package main import ( "unsafe" ) //go:wasmimport env write func write(pointer unsafe.Pointer, length int32) func main() { const str = "Hello, WebAssembly!" write(unsafe.Pointer(unsafe.StringData(str)), int32(len(str))) }

Slide 12

Slide 12 text

12 課題感 Stringとかまだ直接扱えない. // WebAssembly.Memory let mem; const decoder = new TextDecoder(); const write = (ptr, len) => { console.log(decoder.decode(new Uint8Array(mem.buffer, ptr, len))); };

Slide 13

Slide 13 text

どういう経緯で追加された? cmd/compile: replace CallImport with go:wasmimport directive · Issue #38248 · golang/go · GitHub 1. Wasmにはモジュールインポート機能があるが,現状のGoのモジュールインポート は wasm_exec.js にしか対応していない. 2. WASI の標準化が進められており,GoもWASIのサポートをしたい. 3. 最初のステップとして, go:wasmimport を導入したい. → runtime と syscall/js のみサポートしよう. 13

Slide 14

Slide 14 text

GoのWASIサポート all: add GOOS=wasip1 GOARCH=wasm port · Issue #58141 · golang/go · GitHub - WASIをサポートするために syscall でも go:wasmimport を利用できるようにした い. https://github.com/golang/go/blob/2744155d369ca838be57d1eba90c3c6bfc4a3b3 0/src/syscall/fs_wasip1.go#L220-L222 14 //go:wasmimport wasi_snapshot_preview1 fd_write //go:noescape func fd_write(fd int32, iovs unsafe.Pointer, iovsLen size, nwritten unsafe.Pointer) Errno

Slide 15

Slide 15 text

どういう経緯で追加された? cmd/compile: allow the use of go:wasmimport globally · Issue #59149 · golang/go · GitHub - WASI のサポートのために syscall からも go:wasmimport が利用可能になったけ ど,その制限を撤廃しようぜ 😎 → Wasm 関連の機能開発などを活発化させるのが狙い 15

Slide 16

Slide 16 text

16 経緯 - WASIとかそういうのサポートしていくために入った仕様 - 実際に wasip1 で使われている. 現状 - GoからJSの関数を呼び出す時に,グローバル(window)に依存しなくても良くなる - ESモジュールに閉じることができる - Wasmモジュールに直接アクセスできるようになる - 数値しか扱えない 将来 - String なども扱えるようになりそう(期待) まとめ

Slide 17

Slide 17 text

サンプルコード https://gist.github.com/a-skua/c624f3274b03404536b9f0eaa43d78a0 17