-
Notifications
You must be signed in to change notification settings - Fork 172
/
chai2010-golang-wasm.slide
338 lines (228 loc) · 10.9 KB
/
chai2010-golang-wasm.slide
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
# Copyright 2019 <chaishushan{AT}gmail.com>. All rights reserved.
# 安装 Go语言扩展包的 present 工具
# https://godoc.org/golang.org/x/tools/present
# 命令行切换到当前目录, 运行 present 命令
# 浏览器打开 http://127.0.0.1:3999
# 对外提供服务, 关闭 play 功能(安全措施)
# present -http=":3999" -play=false
# -----------------------------------------------------------------------------
Go&WebAssembly简介
Tags: go, golang, wasm, WebAssembly
柴树杉(中国·武汉·光谷)
https://github.com/chai2010
# -----------------------------------------------------------------------------
* 自我介绍(chai2010)
.background chai2010-golang-wasm/images/bgd.jpg
- 主页:Github: [[https://github.com/chai2010/awesome-go-zh/tree/master/chai2010][@chai2010]],Twitter: [[https://twitter.com/chaishushan][@chaishushan]]
- 著作:[[https://github.com/chai2010/advanced-go-programming-book][《Go语言高级编程》]]、[[https://github.com/chai2010/awesome-wasm-zh/blob/master/webassembly-primer.md][《WebAssembly标准入门》]]
个人签名:
# 果戈里: 当歌曲和传说已经缄默的时候,建筑还在说话
- 当歌曲和传说都已经哑巴的时候,只有代码还在说话! - by chai2010
- Less is more!
.image chai2010-golang-wasm/images/weixin.png
* WebAssembly参考图书
.background chai2010-golang-wasm/images/bgd.jpg
.image chai2010-golang-wasm/images/wasm-book.png 500 840
.caption [[https://book.douban.com/subject/30396640/][https://book.douban.com/subject/30396640/]]
# -----------------------------------------------------------------------------
* 认识WebAssembly
.background chai2010-golang-wasm/images/bgd.jpg
# -----------------------------------------------------------------------------
* WebAssembly是Web汇编语言
.background chai2010-golang-wasm/images/bgd.jpg
WebAssembly是⼀种新兴的⽹⻚虚拟机标准。
它的设计⽬标包括:
- ⾼可移植性
- ⾼安全性
- ⾼效率(包括载⼊效率和运⾏效率)
- 尽可能⼩的程序体积
.image chai2010-golang-wasm/images/logo.png 280 280
* WASM最新动态
.background chai2010-golang-wasm/images/bgd.jpg
- 2018.07 - WebAssembly 发布1.0规范
- 2018.08 - Go1.11开始试验性地⽀持WebAssembly
- 2018.08 - Windows2000 运⾏在浏览器中
- 2018年底 - WebAssembly System Interface 项目启动(WASI)
- 2019年底 - Go1.14 将支持WASI规范
*Ending定律*
Any application that can be compiled to WebAssembly, will be compiled to WebAssembly eventually.
⼀切可被编译为WebAssembly的,终将被编译为WebAssembly。
* 2019年美国最赚钱的编程语言
.background chai2010-golang-wasm/images/bgd.jpg
.image chai2010-golang-wasm/images/US-Highest-Paid-Programming-Languages-in-2019.png 500 800
.caption [[https://learnworthy.net/highest-paid-programming-languages-in-2019/][https://learnworthy.net/highest-paid-programming-languages-in-2019/]]
* 浏览器中的Windows2000
.background chai2010-golang-wasm/images/bgd.jpg
.image chai2010-golang-wasm/images/win2k.jpg 500 800
.caption [[https://bellard.org/jslinux/][https://bellard.org/jslinux/]]
# -----------------------------------------------------------------------------
* Go&WebAssembly
.background chai2010-golang-wasm/images/bgd.jpg
# -----------------------------------------------------------------------------
* Go: 你好,WebAssembly
.background chai2010-golang-wasm/images/bgd.jpg
.code ./chai2010-golang-wasm/01-hello/hello.go
$ GOOS=js GOARCH=wasm go build -o hello.wasm
$ node $(shell go env GOROOT)/misc/wasm/wasm_exec.js hello.wasm
你好,WebAssembly
* Go调用JS函数
.background chai2010-golang-wasm/images/bgd.jpg
.code ./chai2010-golang-wasm/02-go-call-js/main.go
$ GOOS=js GOARCH=wasm go build -o hello.wasm
$ node $(shell go env GOROOT)/misc/wasm/wasm_exec.js hello.wasm
* JS回调Go函数
.background chai2010-golang-wasm/images/bgd.jpg
.code ./chai2010-golang-wasm/03-js-call-go/main.go
$ GOOS=js GOARCH=wasm go build -o hello.wasm
$ node $(shell go env GOROOT)/misc/wasm/wasm_exec.js hello.wasm
* 类型转换: Go到JS - 01
.background chai2010-golang-wasm/images/bgd.jpg
.code ./chai2010-golang-wasm/04-go-value-to-js/main.go
* 类型转换: Go到JS - 02 - ValueOf
.background chai2010-golang-wasm/images/bgd.jpg
ValueOf函数:
func syscall/js.ValueOf(x interface{}) Value
类型对应关系:
| Go | JavaScript |
| ---------------------- | ---------------------- |
| js.Value | [its value] |
| js.Func | function |
| nil | null |
| bool | boolean |
| integers and floats | number |
| string | string |
| []interface{} | new array |
| map[string]interface{} | new object |
* 类型转换: JS到Go
.background chai2010-golang-wasm/images/bgd.jpg
.code ./chai2010-golang-wasm/05-js-value-to-go/main.go
* 类型转换: TypeArray
.background chai2010-golang-wasm/images/bgd.jpg
func syscall/js.CopyBytesToGo(dst []byte, src Value) int
func syscall/js.CopyBytesToJS(dst Value, src []byte) int
改进思路:
1. 在全局构造一个[]byte对象,保持地址稳定。
2. 将全局稳定的地址取出,然后JS基于wasm内存构造TypeArray
# -----------------------------------------------------------------------------
* 例子:浏览器中的NES
.background chai2010-golang-wasm/images/bgd.jpg
# -----------------------------------------------------------------------------
* Go语言版本的NES模拟器
.background chai2010-golang-wasm/images/bgd.jpg
.image chai2010-golang-wasm/images/nes-01.png 400 600
.caption [[https://github.com/rbaron/awesomenes][https://github.com/rbaron/awesomenes]]
* 移植到WebAssembly平台 - 01
.background chai2010-golang-wasm/images/bgd.jpg
.image chai2010-golang-wasm/images/nes-02.png 400 600
.caption [[https://chai2010.cn/awesome-go-zh/chai2010/chai2010-golang-wasm/gones-wasm/js/index.html][在线预览]]
* 移植到WebAssembly平台 - 02
.background chai2010-golang-wasm/images/bgd.jpg
.image chai2010-golang-wasm/images/go-wasm-SuperMarioBros.gif 400 600
.caption [[https://chai2010.cn/awesome-go-zh/chai2010/chai2010-golang-wasm/gones-wasm/js/index.html][在线预览]]
* 移植的核心工作 - 01
.background chai2010-golang-wasm/images/bgd.jpg
func (tv *TV) SetFrame(pixels []byte) {
tv.pixels = pixels
jsSetPixels("nes", tv.pixels, SCREEN_WIDTH, SCREEN_HEIGHT)
}
func (tv *TV) ShowPixels() {
jsSetPixels("nes", tv.pixels, SCREEN_WIDTH, SCREEN_HEIGHT)
}
func jsSetPixels(canvas_id string, pixel []byte, width, height int) {
// 更新js空间的pix缓存信息
js.Global().Set("nes_width", js.ValueOf(width))
js.Global().Set("nes_height", js.ValueOf(height))
js.Global().Call("eval", `nes_pix = new Uint8Array(4*nes_width*nes_height);`)
// 复制帧数据到JS空间
nes_pix := js.Global().Get("nes_pix")
js.CopyBytesToJS(nes_pix, pixbuf)
// 绑定到Canvas对象
jsSetPixels := js.Global().Get("jsSetPixels")
jsSetPixels.Invoke(canvas_id, nes_pix, width, height)
}
* 移植的核心工作 - 02
.background chai2010-golang-wasm/images/bgd.jpg
function jsSetPixels(canvas_id, pixel, width, height){
let canvas = document.getElementById(canvas_id);
canvas.width = width;
canvas.height = height;
let ctx = canvas.getContext("2d");
let imgdata = new ImageData(new Uint8ClampedArray(pixel), width, height);
ctx.putImageData(imgdata, 0, 0);
}
改进思路:是否可以将数据直接写入Canvas缓存?
# -----------------------------------------------------------------------------
* WebAssembly汇编语言
.background chai2010-golang-wasm/images/bgd.jpg
# -----------------------------------------------------------------------------
* 手写WebAssembly汇编
.background chai2010-golang-wasm/images/bgd.jpg
.code ./chai2010-golang-wasm/06-wasm-add/add.wat
- module 定义一个模块
- func 定义一个 $add 函数
- export 将 $add 函数导出为 add,对应 res.instance.exports.add
- 函数参数和返回值:func add(a, b int32) int32
* Node.js环境测试add模块
.background chai2010-golang-wasm/images/bgd.jpg
.code ./chai2010-golang-wasm/06-wasm-add/main.js
- add模块只是导出了函数,没有main函数,是一个库
- wasm模块是否可以独立运行?
# -----------------------------------------------------------------------------
* WebAssembly System Interface
.background chai2010-golang-wasm/images/bgd.jpg
# -----------------------------------------------------------------------------
* 手工构造一个WASI例子
.background chai2010-golang-wasm/images/bgd.jpg
.code ./chai2010-golang-wasm/07-wasi-hello/hello.wat /module/,
* 本地运行wasm文件
.background chai2010-golang-wasm/images/bgd.jpg
$ wat2wasm hello.wat
$ wasmer run hello.wasm
hello world
wasmer工具:
[[https://github.com/wasmerio/wasmer][https://github.com/wasmerio/wasmer]]
# -----------------------------------------------------------------------------
* WASI到底是什么?
.background chai2010-golang-wasm/images/bgd.jpg
# -----------------------------------------------------------------------------
WASI其实是一组函数(类似OS的系统调用列表):
;; type iov struct { iov_base, iov_len int32 }
;; func fd_write(id *iov, iovs_len int32, nwritten *int32) (written int32)
(import "wasi_unstable" "fd_write" (func $fd_write (param i32 i32 i32 i32) (result i32)))
WASI定义的函数列表:
[[https://github.com/CraneStation/wasmtime/blob/master/docs/WASI-api.md][https://github.com/CraneStation/wasmtime/blob/master/docs/WASI-api.md]]
Go语言支持WASI吗?
Go1.13还不支持,Go1.14可能会支持
# TODO
# Go输出WASI的wasm
# wasm打包为wapm
# -----------------------------------------------------------------------------
* WebAssembly虚拟机
.background chai2010-golang-wasm/images/bgd.jpg
# -----------------------------------------------------------------------------
- [[https://github.com/go-interpreter/wagon][https://github.com/go-interpreter/wagon]]
- [[https://github.com/wasmerio/go-ext-wasm][https://github.com/wasmerio/go-ext-wasm]]
wagon 是纯Go语言实现
go-ext-wasm是Rust实现,CGO导入
* 例子:WASM虚拟机 - wagon
.background chai2010-golang-wasm/images/bgd.jpg
import (
"github.com/go-interpreter/wagon/exec"
"github.com/go-interpreter/wagon/wasm"
)
func main() {
f, _ := os.Open("add.wasm")
m, _ := wasm.ReadModule(f, nil)
vm, _ := exec.NewVM(m)
// result = add(100, 20)
result, _ := vm.ExecCode(0, 100, 20)
fmt.Println(result)
}
* WebAssembly带来的影响
.background chai2010-golang-wasm/images/bgd.jpg
1. 借助WASM平台,Go语⾔可以开发Web应⽤
2. Go内置WASM虚拟机,吸收其它语⾔的成果
3. 轻量级的Docker
# -----------------------------------------------------------------------------
# by [email protected]