Go: 全部:WebAssembly(“wasm”)支持

创建于 2017-02-02  ·  147评论  ·  资料来源: golang/go

WebAssembly(“wasm”)类似于 Native Client,但不同之处在于其他浏览器计划实现它。

http://webassembly.org/

这已经被问过几次了,所以这是一个跟踪错误。

无论我们是通过 cmd/compile、gccgo 还是 llvm-go 获得它,我们都可以在这里发布更新。

Arch-Wasm NeedsFix

最有用的评论

大家好。 这是我工作的更新:我取得了非常好的进展,这很大程度上归功于 Go 团队和贡献者迄今为止的出色工作。 大多数代码在架构/平台之间共享,因此没有我预期的那么多需要实现。

以下是一些已经正常工作的列表:

  • 在浏览器和 Node.js 中运行生成的 wasm 代码
  • 基本操作、转换等
  • 接口
  • goroutine 和通道
  • 推迟/恐慌/救援
  • 使用 Node.js 时从磁盘读取文件
  • 以下软件包的测试通过: bytes, container/heap, container/list, container/ring, encoding/ascii85, encoding/asn1, encoding/base32, encoding/binary, encoding/csv, encoding/hex, errors, flag, hash/adler32, hash/crc32, hash/crc64, hash/fnv, html, image, image/color, index/suffixarray, math, math/bits, path, sort, strconv, strings, text/scanner, text/tabwriter, unicode, unicode/utf8, unicode/utf16

一些仍然需要工作的事情:

  • 反射
  • 增加 goroutine 的堆栈
  • 垃圾收集
  • 性能优化
  • wasm 文件大小优化
  • 一个不错的 JS 互操作层
  • 使更多包测试通过的许多其他问题

我对一个半月的进步感到非常高兴,而且只是在我的业余时间。 我认为我们很有可能将其引入 Go 1.11。 期待我在 1 月份的下一次更新,因为我将在度假,然后是假期。

所有147条评论

@cherrymui和我详细讨论了 wasm GC 端口的可能性
过去几天:

我们目前的结论是没有有效的方法来实施
当前的 setjmp/longjmp 功能,因此它不是一个可行的目标
一个 gc 端口。 我们需要等到它真正展开堆栈,然后
异常处理支持。

所有其他方面看起来都很好,我们甚至在 wasm 下设计了一个 Go ABI
(在 wasm 堆栈上传递 g 和 SP,在模拟的 Go 堆栈上传递所有其他内容)和
一种通过模拟 MIPS 来修改当前 MIPS 后端以支持 wasm 的方法
注册为 wasm 局部变量。

也许 GopherJS 可以更轻松地支持 wasm。

来自 gopherjs/gopherjs#432:

但是,它不是 GopherJS 可以使用的技术。 GopherJS 在 AST 级别编译,而不是在机器代码级别。

WebAssembly 可以用作普通 Go 编译器的后端

@minux缺少线程或异步 i/o 似乎是一个比我们由于 wasm 怪癖而不得不做的 ABI 变通办法更大的问题。

@minux ,@cherrymui
你能在某个地方更详细地发布你所做的和取得的成就吗?
你可能知道 go-interpreter 社区正在考虑编写一个基于 LLVM 或 wasm 字节码的解释器。
(我们甚至可能有一个 GSoC 学生正在研究 wasm 字节码解释器[1] ,因此,只是“字节码消耗”部分,而不是“通过一些基于 Go 的工具链生成字节码”部分)

最大限度地减少重复工作量和各种组件之间的阻抗失配将是非常好的。

我强烈建议将此作为战略功能。 考虑一下,在短短几年内,Web 程序员将成群结队地选择他们选择的语言来编译成 Web 程序集。 我们越早参加比赛越好。 Mozilla 正在努力推动 Rust 成为首选的 Web 汇编语言......

赞同@RaananHadar所说的话。 如果规范不能满足 Go 的需求,那就太可惜了,特别是考虑到 Go 的运行时是独一无二的。

编辑:为这个评论的 MeToo 性质道歉 :) 感谢指针布拉德。

提醒: https ://golang.org/wiki/NoMeToo

WebAssembly 堆栈机器上下文由线性内存和操作堆栈组成。 IIUC,可以通过保存以下内容来保存 VM 上下文:

  1. 当前PC,字节码字符串
  2. 线性记忆和
  3. 操作栈

到 VM 上下文结构中保存的上下文的全局列表(如果有)。

因此,setjump 应该简单地恢复这些值,并像往常一样继续解释器循环(这类似于 emacs 字节码 VM 实现信号的方式:https://github.com/emacs-mirror/emacs/blob/master/src /bytecode.c#L785)。 可以在此之上实现一个异常系统,尽管我不确定它的性能如何。

此外,webassembly 规范提到字节码中任何时刻的堆栈高度是静态已知的,这使得所有堆栈操作都等同于对堆栈上每个位置唯一的寄存器的操作。 本文描述了一种实现这种堆栈的方法 -> 将堆栈机器代码转换为本机代码的寄存器映射,允许我们像往常一样使用 setjmp/longjmp。

编辑:使用带有特殊WasmException{}值的panic()recover()来发出异常信号怎么样? recover已经完成了堆栈展开的艰巨工作,从捕获的异常中恢复后恢复解释器循环应该不难。

是的,基本上与@cherrymui的讨论得出了类似的发现。

@cherrymui的初始设计是这样的:
(这个阶段的重点是让 $GOROOT/test/sieve.go 工作,没有异步 IO
经过考虑的。)
我们重用 MIPS 端口,将 31 个 MIPS 寄存器映射为 WASM 本地
变量并且仅使用 WASM 堆栈
对于中间结果。 我们不能使用 WASM 的函数调用机制
大多数 Go 函数,因为
缺乏堆栈展开支持。
更改 mips objlink (cmd/internal/obj) 以模拟每个 MIPS 指令
带有各自的 WASM 指令。
这使得 setjmp/longjmp(又名 runtime.gogo)的实现变得微不足道,并且
重用了很多现有的工作。

Go 已经需要实现自己的堆栈,独立于 WASM 堆栈,
因为 Go 需要可复制的
堆栈、堆栈指针映射和堆栈展开支持,它们不是
可从 WASM 获得。
(此策略也与 LLVM 端口一致,我们不能将 LLVM 堆栈用于
几乎相同的原因
(除非我们向 LLVM 添加自定义后端传递以正确编码堆栈指针
地图)。)

我们可能需要使用大开关来线程间接跳转? 这是
类似于 NestedVM 的方法。
http://nestedvm.ibex.org/

如果我们决定实现一个原生 WASM 后端,那么我们可以这样做:
Go ABI 是:
(模拟的)Go 堆栈上的所有参数(包括结果),
在函数入口处,WASM 堆栈上有以下内容:
模拟SP,g。

讨论发生在一个多月前,我可能忘记了一些
此时的详细信息。

IIUC,您可以完全丢弃 WASM 堆栈(根据规范)。 可扩展和可复制的 Go 堆栈仍然需要研究。

是的,我提到的初始设计仅使用 WASM 堆栈
计算中使用的中间体。 所有数据要么在 Go 堆上(线性
memory) 或 WASM 局部变量中的伪寄存器。

我不希望 WASM 规范包含移动/分段和复制堆栈。
WASM 所针对的主流语言很少使用它。

@bradfitz @minux @vibhavp golang 中 wasm 的当前状态是什么? 自 3 月 13 日以来,什么都没有发生! 未来是否有可能将 golang 转换为 wasm? 可能有任何路线图吗?

如果有人决定实施 wasm 支持,我可以为非全局任务提供时间

@SerkanSipahi ,没有人在做这个。 此错误标记为 LongTerm。 如果有事情开始发生,您会在此处看到更新。

一个好的路线图?

我们有 DELVE 和 GDLV 用于使用 GUI 调试 golang。 它在所有台式机上也运行良好,Perf 也非常出色。
https://github.com/derekparker/delve
https://github.com/aarzilli/gdlv

现在,GDLV 基于 NUCULAR,它带有一些漂亮的抽象。
https://github.com/aarzilli/nucular

所以我认为这将是一个很好的基础来做这里已经做过的事情:

  • 演示: http ://shi-yan.github.io/AssortedWidgets/
  • 代码: https ://github.com/shi-yan/AssortedWidgets

现在也有 5 个 WASM go 库:
https://github.com/search?l=Go&q=webassembly&ref=simplesearch&type=Repositories&utf8=%E2%9C%93

我相信 NaCl 被 Go 生态系统的各个部分使用。 也就是说,它不仅仅被 Chrome 使用。 无论如何,该博客公告是关于 PNaCl 的,虽然它提供了与 NaCl 类似的功能,但实际上是基于不同技术的完全不同的产品。 因此,目前从 Go 中移除 NaCl 支持还为时过早。

无论如何,我们是否从 Go 中删除 NaCl 与我们是否添加对 Web Assembly 的支持无关。

我会说 PNaCl 只是 NaCl 的扩展,以提供与平台无关的代码https://developer.chrome.com/native-client/nacl-and-pnacl我在这里询问了 NaCl 弃用 - https://groups.google。 com/d/topic/native-client-discuss/wgN2ketXybQ/discussion

是否可以获得仍然使用 NaCl 的 Go 生态系统的各个部分的列表?
一个一个地完成它将使过渡到 WebAssembly 变得更加有趣。

我会说 PNaCl 只是对 NaCl 的扩展

你可以说任何你想说的,但这并不意味着你是对的。 它们是完全不同的 ISA,NaCL 只是具有一些限制的目标 ISA(x86/arm),而 PNaCl 是用于抽象机器的完全不同的 ISA。

Go 从来不支持 PNaCL,而且 Go NaCL 端口也不适合 Chrome。 它与 Chrome 无关,无法在浏览器中使用。 Chrome 是否放弃 NaCL 或 PNaCL 与 Go 无关。 Nada,无,没有相关性。 这还要说多少遍? 当然,如果 NaCL 被完全放弃,那么 Go 在某些时候也将被迫放弃它。

Go 中的 WebAssembly 支持与 NaCL 完全无关。 Go 可能会也可能不会获得 WebAssembly 支持。 是否或何时可能获得此类支持与 NaCL 端口的状态无关。

这是我们使用 nacl 的生态系统的一个非常重要的部分:https: //play.golang.org/p/MfJIq8wb5-

(运行服务器端,而不是浏览器中的 nacl)

Chrome 是否放弃 NaCL 或 PNaCL 与 Go 无关。 Nada,无,没有相关性。

那么谁会支持沙盒加载器和工具链呢? 它是从 Chrome 项目导入的,该项目将工作转向 WebAssembly。 跟随并查看 Go 游乐场是否已经可以从 NaCl 沙箱移植到 WebAssembly 沙箱不是明智之举吗? 它也可以在服务器端运行。

我认为每个人都赞成支持 WebAssembly。

讨论离开 NaCl 的时间是在 WebAssembly 完全工作之后。 在那之前讨论它是没有意义的。

@ianlancetaylor ,你能澄清“在 WebAssembly 完全正常工作之后”吗?

乍一看, webassembly.org似乎说“WebAssembly 的初始版本已达到跨浏览器共识”,并且所有浏览器供应商的当前或未来浏览器版本都可以使用 wasm。

@vine77我的意思是在 WebAssembly 完全为 Go 程序工作之后,至少现在和 NaCl 一样工作。

那么 WebAssembly 为 Go 程序工作应该通过的下一个测试是什么?

@techtonik我觉得这里有些混乱。 当我们说 WebAssembly 应该适用于 Go 程序时,我们的意思是 Go 编译器应该生成可以在浏览器中运行的 WebAssembly 代码。 我们的意思是您应该能够编写类似GOOS=wasm go build hello.go的东西并获得可以在浏览器中运行的程序。 我们甚至离那一点都不远。 我们甚至还没有开始。 所以没有“下一个测试”。 有很多工作要做。 而且,据我所知,没有人在积极研究它。

@ianlancetaylor
golang 有 4 种实现。 一个非常令人印象深刻。 有关链接,请参阅我之前的评论。

男孩,这条线就像雪佛兰蔡斯汽车,后座上的孩子们尖叫着“我们还在那里吗”:)

@joeblew99 :这些链接都不是可以编译到 WebAssembly 的东西。
它们类似于用 Go 编写的 WebAssembly -> amd64 编译器。

我怕你会这么说。 很公平。
那么“培养”需要什么? 所以大家都知道...
Gopherjs 在编译器工具链架构/代码生成中犯了同样的错误?

有一个很长的清单。 大多数都与垃圾收集有关,一种或另一种方式。

  • 在 SSA 后端生成 WebAssembly 代码。 后端用于注册机器,适应 WebAssembly 的栈机器需要一些工作。
  • 什么是指针? WebAssembly 没有指针类型。
  • 我们如何内省堆栈? 我们当然需要它来进行垃圾收集,但也需要恐慌/恢复、回溯打印等。
  • 我们如何暂停/恢复一个 goroutine?
  • 我们如何布置堆? WebAssembly 本质上只提供 sbrk。 我们需要更通用的地址空间布局。 我们在哪里存储有关 span、ptr/nonptr 位等的信息?
  • 多线程。 WebAssembly 目前没有线程的概念,例如,我们需要执行并发 GC。 我们还需要锁,也许还需要原子操作。
  • 我们如何为 os 和 net 等软件包提供对外部世界的访问?
  • WebAssembly 不支持“goto”。

这可能不是一个完整的列表。

当我们说 WebAssembly 应该适用于 Go 程序时,我们的意思是 Go 编译器应该生成可以在浏览器中运行的 WebAssembly 代码。

@ianlancetaylor首先定位非网络会更容易吗? NaCl 也被设计为首先在浏览器中运行,但随后获得了 Go 当前使用的独立于浏览器的加载程序。 没有浏览器的 WebAseembly - http://webassembly.org/docs/non-web/ - 它谈到了用于测试的最小外壳。

@randall77是否可以从该列表中取出一个可操作的清单? 就像一个主问题,其中包含指向进一步详细研究每个方面的问题的链接?

@techtonik wrt non-web: @vibhavp正在 GSoC 实习的背景下进行这项工作,我在上面提到了一些帖子。
它在那里: https ://github.com/go-interpreter/wagon

@techtonik :我认为这样一份清单的正确位置是关于支持 wasm 的提案文件。 一旦这样的提议被接受和/或人们正在积极研究它,他们当然可以将问题用于个别任务。 在这一点上还为时过早 - 我知道没有人积极从事任何一项工作(提案或代码)。

我同意提案文档。
我所做的所有/矛盾都在这个线程中,只需要将它包装在一起,并带有一个可以让风险/回报平衡阶段的路线图。

我也希望看到它也能解决图形问题,因为它对我来说就像拇指酸痛一样突出。

我是GopherJS的作者,这是一个从 Go 到 JavaScript 的编译器。 我写了那个项目是因为我坚信应该有在浏览器中使用 JavaScript 的替代方案,比如 Go 和其他替代方案。 我对编译器、SSA、机器架构等有相当的了解,但我可能遗漏了很多细节,因为我还没有为机器代码编写编译器后端。 这就是为什么我觉得没有资格编写完整的提案文档。 尽管如此,我还是很想得到一些关于我对 Go 和 WebAssembly 想法的批评性反馈。

在查看 WebAssembly 时,我觉得它与 x86 或 arm 等通常的机器代码目标非常不同。 例如,它的架构是堆栈机而不是寄存器机。 这意味着它并不立即适合作为 Go 编译器最后阶段的另一个目标,仅次于 x86 和朋友。 一种解决方案可能是不把它放在那里,而是用一种截然不同的方法来生成 WebAssembly。 这种方法的代码需要存在于现有的编译器阶段之外,这根本不好。 在这种情况下,甚至可以考虑编译器的一个分支。 简而言之:我没有看到这种情况发生。

可能有另一种选择:模仿我们需要的东西。 我们可以使用堆栈机器来模拟寄存器机器,并希望以合理的性能方式这样做。 WebAssembly 具有带有加载和存储指令的线性内存,这很好。 我们根本不会使用 WebAssembly 的call指令,而是使用我们自己的堆栈管理和调用机制。 堆栈将存在于该线性内存上并由 Go 运行时管理。 堆栈指针将是一个全局变量。 所有代码都将存在于一个 WebAssembly 函数中。 顶层将是一个巨大的 switch 语句(或基于 WebAssembly 的br_table等效项),每个函数都有一个分支。 每个函数都有另一个 switch 语句,每个 SSA 基本块有一个分支。 我在这里省略了一些细节,但总的来说,这对我来说似乎是一台不错的注册机。 当然,这在很大程度上取决于 WebAssembly 将这些构造转换为实际机器代码的能力。

所以请告诉我:我是不是完全天真和疯了? 然后我很乐意推迟我的想法,直到我了解更多。 如果没有,那么这可以作为一些实际提案文档的起点。 谢谢。

除了 Go 端所需的所有工作之外,WebAssembly 可能还需要一些东西才能让 Go 运行时定位它。

WebAssembly 还没有线程,但它在路线图上并且有一个规范。 https://github.com/WebAssembly/threads

关于垃圾收集,听起来未来可能会有多种选择,基于林克拉克的谈话https://youtu.be/HktWin_LPf4?t=28m31s

28:31
所以,今天,如果你愿意,你可以用代码交付你自己的垃圾收集器,但是
由于一些原因,速度很慢,社区组正在使 WebAssembly 代码成为可能
仅与内置 GC 一起使用,这是浏览器高度优化的
一直在努力,所以它会运行得很快,你将拥有这种集成。

与 gomobile 一样,有一个语言桥梁需要弄清楚。

@randall77还提到线程是 GC 的要求。 这真的是第一个版本的硬性要求吗? 并发也可以在单个线程中完成。

关于 GC 的实施,我个人的看法是,我不相信一个 GC 可以统治所有这些。 我宁愿让 Go 有一个特定于 Go 的 GC,而让 Python 有一个特定于 Python 的 GC。 通过在 WebAssembly 的线性内存上完全管理我们自己的堆和堆栈,据我目前所见,我们应该能够使用 Go 已经拥有的 GC。

@neelance是的,多个真正的 WebAssembly 线程是一个不错的选择,而不是严格的要求。

WebAssembly 的 GC 提案仍在进行中。 有兴趣的可以在这里参与:

https://github.com/WebAssembly/gc

@neelance ,我对编译器、SSA、机器架构等一无所知。你能告诉我你所描述的会如何影响二进制大小吗? 如果我理解正确,尺寸效率是WebAssembly 的高级目标之一。 它也应该是这个 Go->WebAssembly 编译器的优先事项之一,对吧?

@alxkchr我的经验是,由于代码生成样板导致的重复可以通过应用 gzip 得到很多补偿。 不过,就二进制大小而言,我的建议并不是最有效的解决方案。 尽管如此,一些可以在合理时间内实施的解决方案总比没有解决方案好,对吧? ;-) 对我个人而言,二进制大小也不是首要任务之一。

仅供参考:我已经开始实施这个。

@neelance有史以来最好的消息 :) 你遵守规范吗? (我希望)

围棋规范? 它是普通 Go 编译器的新后端/目标,因此规范已经存在。 ;)

我的意思是wasm规格:)

@neelance

仅供参考:我已经开始实施这个。

你能分享一下将使用什么方法来解决

我们目前的结论是没有有效的方法来实施
当前的 setjmp/longjmp 功能,因此它不是一个可行的目标
一个 gc 端口。 我们需要等到它真正展开堆栈,然后
异常处理支持。

(https://github.com/golang/go/issues/18892#issuecomment-276858667)

@neelance :我知道现在还为时尚早,但我认为将 wasm 命名为 GOARCH wasm32会更明智(同样适用于包)

@sbinet值得考虑的是 ARM 架构/包被命名为armarm64 (类似mipsmips64 )而不是arm32arm64 。 但是,我不知道这应该被认为是一个好例子还是坏例子。

@SerkanSipahi我最初的目标是 V8(nodejs/chrome),并使用https://webassembly.github.io/spec/作为文档说明该做什么。

@stuart-warren 是的,我的 WIP 在那个分支上。 但是,不要尝试使用它,它现在不容易构建,并且充满了复制的代码和存根/黑客。 当它达到某个 alpha 状态时,我会在这里宣布它。

@cznic如上所述,我根本没有使用 wasm 的call指令,而是在线性内存上管理自己的堆栈。 这样就可以实现setjmp/longjmp。

@sbinet实际上它将是一个 64 位架构,因为 wasm 具有 64 位操作。

@neelance不完全是。 WebAssembly 规范目前仅支持 32 位地址空间,计划稍后提供wasm64规范

有趣,谢谢你的链接。 我们可能想稍后再谈。 目前我将所有内容存储在 64 位变量中,因此intuintuintptr的大小均为 64 位。 但是,只有前 32 位用于寻址存储器。 这在开始时更容易实现。

听起来像 wasm64p32 (遵循 nacl 命名),或者什么
相似的。

2017 年 11 月 4 日上午 5:28,“Richard Musiol” [email protected]写道:

有趣,谢谢你的链接。 我们可能想稍后再谈。
目前我将所有内容存储在 64 位变量中,因此 int、uint 和 uintptr
所有的大小都是 64 位。 但是,只有前 32 位用于
寻址内存。 一开始这更容易实现。


您收到此消息是因为您订阅了此线程。
直接回复此邮件,在 GitHub 上查看
https://github.com/golang/go/issues/18892#issuecomment-341889653或静音
线程
https://github.com/notifications/unsubscribe-auth/AAgwpPTbfHRmoYNXLQfcPMVnARxb0UGrks5szEpjgaJpZM4L0o7D
.

听起来像 wasm64p32 (遵循 nacl 命名),或者什么
相似的。

我认为有两个数字没有意义,因为只会有一个架构(可以选择地址空间大小)。 来自webassembly.org

wasm32 和 wasm64 都只是 WebAssembly 的模式,由模块头中的标志选择,并且不暗示线性内存处理方式之外的任何语义差异。

我认为有两个数字没有意义,因为只会有一个架构(可以选择地址空间大小)。 来自 webassembly.org:

wasm32 和 wasm64 都只是 WebAssembly 的模式,由模块头中的标志选择,并且不暗示线性内存处理方式之外的任何语义差异。

这是一个有抱负的声明。 这可能是真的,但 WebAssembly CG / WG 还没有充分探索 wasm64,让我确信该声明是准确的。

@neelance工作吧。 名称很容易在以后更改。

我知道 Go 直接编译为机器指令(AFAIK),但我想知道是否有人曾经将 Go 编译为 C。尝试 Go --> C --> wasm 会很有趣(虽然效率不高)。

@TomerHeber可以翻译成 C++,而不是编译,但这可能比编译成 wasm 本身更有效

大家好。 这是我工作的更新:我取得了非常好的进展,这很大程度上归功于 Go 团队和贡献者迄今为止的出色工作。 大多数代码在架构/平台之间共享,因此没有我预期的那么多需要实现。

以下是一些已经正常工作的列表:

  • 在浏览器和 Node.js 中运行生成的 wasm 代码
  • 基本操作、转换等
  • 接口
  • goroutine 和通道
  • 推迟/恐慌/救援
  • 使用 Node.js 时从磁盘读取文件
  • 以下软件包的测试通过: bytes, container/heap, container/list, container/ring, encoding/ascii85, encoding/asn1, encoding/base32, encoding/binary, encoding/csv, encoding/hex, errors, flag, hash/adler32, hash/crc32, hash/crc64, hash/fnv, html, image, image/color, index/suffixarray, math, math/bits, path, sort, strconv, strings, text/scanner, text/tabwriter, unicode, unicode/utf8, unicode/utf16

一些仍然需要工作的事情:

  • 反射
  • 增加 goroutine 的堆栈
  • 垃圾收集
  • 性能优化
  • wasm 文件大小优化
  • 一个不错的 JS 互操作层
  • 使更多包测试通过的许多其他问题

我对一个半月的进步感到非常高兴,而且只是在我的业余时间。 我认为我们很有可能将其引入 Go 1.11。 期待我在 1 月份的下一次更新,因为我将在度假,然后是假期。

其中一些任务可以并行化吗? 对于假期黑客来说,有些位似乎很有趣。

随意查看它并在我的 fork 上创建一个 PR。 你也可以在 Gophers Slack 上找到我。

一个研究领域可能是优化堆栈的使用。 现在,寄存器分配阶段为每个操作分配寄存器(wasm 中的局部变量)。 get_localset_local总是在每次操作之前和之后使用。 如果该值可以简单地保留在堆栈上以供以后的某些操作使用,则这是不必要的。 如果使用此寄存器,我建议添加一个伪寄存器REG_STACK并让指令生成器跳过get_localset_local 。 然后让regalloc在适当的时候使用这个寄存器。

回覆:

一个不错的 JS 互操作层

目前是否有一种健全的方法可以为 wasm 实现这一点? 我认为 Dom/js 互操作仍然是 wasm 的出路。 如果这可能的,那将是巨大的!

您可以导入和导出可以具有float64int32参数的函数,并且您拥有共享的线性内存。 其他一切都可以围绕它构建。 只有垃圾收集不会那么好。

(我一直试图在你的(@neelance)回购上发布这个,但我不知道如何发布问题......)

是否可以使用wabt工具链而不是调用/导入js.foo
我发现与wabt交互而不是完整的nodejs安装更容易:)

(我也在尝试解释一个简单的main.go程序,在这里翻译为a.wasm :go-interpreter/wagon#36...)

我已经在我的 fork 上启用了问题,请随时在那里发帖。

我真的不明白你的问题。 你说的是wasm-interp吗? 需要编译和运行 wasm 字节码,并且您需要一些 JS 环境来与系统的其余部分进行交互,例如打印到控制台。

这很棒。 对于那些想要尝试编译和执行 Go to wasm 的人 -

  1. 创建一个打印到控制台的简单 hello world 程序。
  2. GOOS=js GOARCH=wasm ./bin/go build -o out.wasm wasm.go
  3. ./misc/wasm/go_js_wasm_exec out.wasm

享受 !

如果您将go_js_wasm_exec链接到 PATH,那么您甚至可以使用go run 。 ;-)

大家好,Go for WASM 的垃圾收集情况如何? 我们开始讨论引入 Crystal ,看起来 Crystal 可能与 Go 目前在 GC 方面存在相同的问题。 在这种情况下,我们有什么方法可以合作或帮助 WebAssembly 工作组吗?

请随时加入上面提到的线程,或者让我们知道我们可以在哪里聊天/可能就这个问题进行合作。

在 WASM 在该领域成熟之前,Opal 路径可能是目前更理智的方法,但在走这条路之前确定这一点会很好。

嘿伙计们,我想分享过去几个月我一直在工作的东西,因为我认为很多底层代码都是相关的: https ://github.com/matthewmueller/joy

我现在的目标是 JS(ES3),但是编译器为所有声明(函数、变量等)实现了依赖关系图。 然后它对图形进行排序并仅翻译程序中使用的声明。

我不认为使用这个图和目标 WebAssembly 会太难。 我渴望尽我所能提供帮助和合作。

有关更多信息,这里有一些相关链接:

关于上面 Crystal 的 GC 问题,这可能也适用于 Go,请注意@kripken的评论和以下讨论: https ://github.com/WebAssembly/binaryen/issues/1312#issuecomment -348409211

我希望每个人都度过了愉快的假期。 这是承诺的更新:

自从我上次更新以来,我设法让反射、堆栈增长和垃圾收集启动并运行。 额外的改进使得 136 个 stdlib 包中的 104 个测试现在通过了。 此外,许多编译器测试都是绿色的。 进展顺利!

请记住,我目前专注于功能支持和正确性。 我还没有对性能或输出大小进行任何优化。

我为这个实验喝彩(和@neelance ty 对于 GopherJS相比Promise更好的 goroutines 表示赞赏,你可能把我从 C++ 中救了出来!),所以以下只是试图添加潜在有用的信息和甚至可能是为了提高人们对 Go 和 WASM 目标之间不一致的认识。 也有可能为一些读者澄清这个问题。 还因为我想要一个合适的地方来转储我在独立思考如何将 gorountines 之类的东西编译到 WASM 时发现的以下@rossberg引用。

@neelance回复

@cznic回复

@neelance写道

我们根本不会使用 WebAssembly 的call指令,而是使用我们自己的堆栈管理和调用机制。 堆栈将存在于该线性内存上并由 Go 运行时管理。 堆栈指针将是一个全局变量。 所有代码都将存在于一个 WebAssembly 函数中。 顶层将是一个巨大的 switch 语句(或基于 WebAssembly 的br_table等效项),每个函数都有一个分支。 每个函数都有另一个 switch 语句,每个 SSA 基本块有一个分支。

您能否分享一下将使用什么方法来解决:

@minux写道

我们目前的结论是没有有效的方法来实施
当前的 setjmp/longjmp 功能,因此它不是一个可行的目标
一个 gc 端口。 我们需要等到它真正展开堆栈,然后
异常处理支持。

@cznic如上所述,我根本没有使用 wasm 的call指令,而是在线性内存上管理自己的堆栈。 这样就可以实现setjmp/longjmp。

根据 WASM 的“共同设计者”“规范作者”的说法, call的限制使其不适合 Go,这与安全性/安全性有关:

@rossberg写道

您不能轻易地“替换”调用堆栈,因为无法具体化返回地址 (*)。 但是,如果需要,您可以在线性内存中为局部变量实现影子堆栈。

事实上,WebAssembly 目前根本没有公开任何内置“堆栈”的概念。 与许多其他设计决策一样,这很重要:因为 Wasm 运行在 Web 上,所以它必须是“安全的”。 这就是为什么它是有类型的、没有未定义的行为、代码与内存分离(并且不可寻址)、检查函数类型的强制转换等。拥有明确的函数概念还可以带来其他好处,例如有效的寄存器分配、并行或惰性编译,有用的调试工具等。

控制流确实是半结构化的:分支实际上只是中断和继续,因此您无法构建不可约的控制流。 这也是一个特点。

[…]

(*) 通过将整个程序编译为单个循环函数,您大概可以将带有索引的显式返回地址模拟成一个巨大的表跳转。 但这可能会非常缓慢,并且会破坏 WebAssembly 生态系统的大部分内容

那么@neelance正在尝试的与 WASM 生态系统的性能和互操作性可能不是最理想的吗?

引用@neelance 优化GopherJS 性能的技能

我不知道您所说的“与 WASM 生态系统的互操作性”是什么意思,所以我无法对此发表评论。 关于性能,我可以告诉你:

是的,当前的方法不是在 WebAssembly 中表达控制流的最佳方式,但它在今天仍然有效。 也许将来可以更多地使用 WebAssembly 的call指令,但是为此,WebAssembly 需要添加更多功能,并且需要在 Go 端进行更多工作才能与之兼容。 我宁愿拥有 80% 性能的东西,而不是 100% 但只是假设的东西。 ;-)

如果您对更多技术细节感兴趣,请在https://invite.slack.golangbridge.org/ 上通过#webassembly 与我交谈。

我不知道您所说的“与 WASM 生态系统的互操作性”是什么意思,所以我无法对此发表评论。

也许@rossberg所指的_“击败WebAssembly 生态系统的大部分”_ 是指与生态系统中的工具和其他语言的互操作性,这些工具和其他语言并没有回避call和受保护的调用堆栈,基本上是模拟你的自己的延续使用switch表?

但为此,WebAssembly 需要添加更多功能

我希望 WASM 能够更好地适应带有 goroutines(绿色线程)的语言,因为它们无疑优于堆栈展开 JavaScript Promise模型。

我宁愿拥有 80% 性能的东西,而不是 100% 但只是假设的东西。 ;-)

哦,我完全同意,这就是为什么我要确保在我之前的帖子之前,我会为你的多产努力鼓掌。

在 web/WASM 上越流行,我们可以让 Go 或其他具有绿色线程的语言,那么也许我们有更好的机会获得更好的 WASM 原语(例如,类似于gcc 的-fsplit-stack ?)最终获得更好的性能.

如果你的实现在当前 WASM 的限制下真正实现了 80% 的最佳性能,我会感到惊喜。 如果性能结果过于糟糕,那么它可能会限制绿色线程与基于 JavaScript Promise回调模型的演示(如果我们假设它是“击败大部分 WebAssembly 生态系统”的讽刺潜力)设计一直由优化 JavaScript 的优先级驱动:-)。

另请注意,我正在考虑(还没有确定的决定)将 typeclass 泛型作为转译器添加到 Go 中(并提供我对 Go 2 的泛型提案的分析),因此我也可能参与尽我所能尝试增加人气。

@shelby3请停止使用使您的文本太小以至于无法阅读的格式。 如果您认为某些内容不值得人们阅读,请不要一开始就写出来。 在不提示隐藏内容的情况下使其不可读,使读者花费两次(或更多)时间试图破译它。 我认为这与您的初衷相反。

@shelby3我已编辑您的帖子以停止使用小文本格式。 请停止这样做。

更改https://golang.org/cl/102835提到这个问题: go/build, cmd/dist: add js/wasm architecture

更改https://golang.org/cl/103255提到这个问题: wasm: add scripts for running WebAssembly binaries

更改https://golang.org/cl/103256提到这个问题: cmd/compile: add SSA config options noAvg and noHmul

更改https://golang.org/cl/103275提到这个问题: cmd/compile/internal/gc: factor out beginning of SSAGenState.Call

更改https://golang.org/cl/103295提到这个问题: cmd/compile: add wasm architecture

更改https://golang.org/cl/103535提到这个问题: cmd/compile: wasm stack optimization

更改https://golang.org/cl/103795提到这个问题: cmd/link: add wasm architecture

更改https://golang.org/cl/103877提到这个问题: runtime: add js/wasm architecture

更改https://golang.org/cl/103915提到这个问题: internal/bytealg: add wasm architecture

好吧,看起来很多 CL 开始飞了。
我们在移植政策方面做得如何: https ://github.com/golang/go/wiki/PortingPolicy?
特别是,建设者会是什么样子?
我假设@neelance您正在注册维护端口?
(如果其中一个 CL 说明了所有这些,我深表歉意,我还没有阅读所有这些。)

是的,我要维护港口。 @bradfitz目前正在研究设置构建器。

更改https://golang.org/cl/106995提到这个问题: sync/atomic: add wasm architecture

更改https://golang.org/cl/106996提到了这个问题: math: add wasm architecture

更改https://golang.org/cl/106997提到了这个问题: time: add wasm architecture

https://golang.org/cl/106998提到这个问题: mime: add wasm architecture

更改https://golang.org/cl/109195提到了这个问题: syscall/js: add package

更改https://golang.org/cl/109976提到了这个问题: syscall: enable some nacl code to be shared with js/wasm

更改https://golang.org/cl/109977提到这个问题: os: add js/wasm architecture

更改https://golang.org/cl/109995提到这个问题: net: add js/wasm architecture

更改https://golang.org/cl/110095提到这个问题: crypto: add js/wasm architecture

更改https://golang.org/cl/110096提到这个问题: all: skip unsupported tests for js/wasm

更改https://golang.org/cl/112736提到这个问题: env/js-wasm, dashboard: add start of a js-wasm builder

更改https://golang.org/cl/113515提到这个问题: misc/wasm: make wasm_exec.js more flexible

在阅读了 Go 文档的 WebAssembly 架构之后,特别是在 Node 的“fs”模块上构建的 JavaScript 系统调用实现,并且在浏览器方面基本上没有实现,我想知道我们是否可以或想要尝试使用_new_ 浏览器 API? 具体来说, FileSystem API规范似乎可以支持至少一些系统调用。 (FileSystem 仍然是编辑草稿,仅在 FireFox、Chrome 和 Opera 上实现。此外,它在后两者上加上了 'webkit-' 前缀。)
如果您认为这可能是一种不错的方法,我可以尝试进行概念验证。

更改https://golang.org/cl/114197提到这个问题: runtime, sycall/js: add support for callbacks from JavaScript

大家好,我很喜欢@neelance所做的工作,我想知道是否通过这个 WASM 实现(比如说,它的第一个版本),是否也可以使用cgo 。 嵌入 C 代码,编译到 GO,编译到 WASM。 那将是一个该死的超级大国。 你们都做得很棒。 惊人的。

@cmaster11 很高兴听到你喜欢它。 :) 关于您的问题: cgo不会将 C 编译为 Go,而是使用它们各自的编译器将两种语言编译为机器代码,然后将结果合并到一个二进制文件中。 您已经可以使用 emscripten 将 C 代码编译为 WebAssembly。 理论上,应该可以在运行时加载两个 WebAssembly 二进制文件并让它们交互。 但是,我认为 Go 项目不太可能在不久的将来花时间来促进这个用例。

显然主要是千禧一代

@shelby3我可能比你大,我对你投了反对票。 这里的问题只是你无法沟通。

这不是权力的问题。 @andybons实际上通过编辑您的帖子使您受益,以便其他人可以阅读。

没有 webidl 的 js/wasm 支持意味着我们无法在 Web 浏览器中与其他语言进行很多互操作。 wasm 架构似乎没有提到任何关于 webidl 的内容。

当应用到 c++ Foo 类时,我仔细查看了 emscripten webidl python 工具,如下所示。
我希望看到通过 webidl 以与 Foo 类相同的方式公开的 golang 鸭类型。
这个基本原理是与同时加载的其他 wasm 模块互操作,但我们需要可用的 idl 以便能够包含和调用它们的编组存根。 否则,我们需要某种对象查看器来确定不同 wasm 文件中可用的调用签名。

python /usr/lib/emscripten/tools/webidl_binder.py Foo.idl glue
This generates:
glue.cpp
glue.js
WebIDLGrammar.pkl

emcc -v Foo.cpp my_glue_wrapper.cpp --post-js glue.js -o output.js
This generates:
output.js
output.wasm

emrun --list_browsers
emrun --browser chrome handcrafted_Foo.html 
emrun --browser firefox handcrafted_Foo.html 
firefox handcrafted_Foo.html &
chrome handcrafted_Foo.html &

$ cat Foo.h

#ifndef FOO_H
#define FOO_H (1)

class Foo {
public:
  int getVal();
  void setVal(int v);
 private:
  int nValue;
};

#endif

$ cat Foo.cpp

#include "Foo.h"

int Foo::getVal() {
  return nValue;
}

void Foo::setVal(int v) {
  nValue = v;
}

$ cat my_glue_wrapper.cpp

#include "Foo.h"
#include "glue.cpp"

$ cat Foo.idl

interface Foo {
        void Foo();
        long getVal();
        void setVal(long v);
};

$ cat handcrafted_Foo.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">
    <title>WebAssembly Sample</title>
  </head>

  <body>
    <h1>Web Assembly</h1>

    <div class="output">
        <pre id="log"></pre>
    </div>

    <script src="output.js"></script>
    <script>      
      "use strict";


    function log() {
        document.querySelector('#log').textContent += Array.prototype.join.call(arguments, '') + '\n';
    }

    Module.onRuntimeInitialized = _ => {
      log(`blah `);
      var f = new Module.Foo();
      f.setVal(200);
      alert(f.getVal());
      log(`blah `);
    };

    </script>

  </body>
</html>

@omac777 ,与其他语言的互操作不是 Go 的 1.11 初始 WebAssembly 支持的目标。

好的。 我可以理解 webidl 不是短期目标,但我确实对如何使 wasm 输出有用存在疑问。 首先回到上面定义的用于 emscripten c++ 及其 idl 的 Foo 类。 假设我创建了一个与之匹配的 golang 鸭类型。 然后说我将这些函数导出为 C 函数,以便它们可以从 C++ Foo SetVal 和 GetVal 实现中调用。 我知道它会因此变慢,但尝试在 go 中构建所有实现将是长期目标。

如何创建 foo.go.wasm.a 和 foo.go.wasm.so? 每个 foo.wasm 都需要自己的 foo.go.js 吗?
如果生成了一个充满不同 foo 的库,那么还会生成 otherfoos.go.a.js 吗?

如何将 go.wasm.a 和 go.wasm.so 链接到生成的 emcc output.wasm,如下所示:
emcc -v Foo.cpp my_glue_wrapper.cpp --post-js glue.js -o output.js foo.go.wasm otherfoos.go.wasm.a

例如,如何从 go 中的 wasm 链接 emcc 支持的 sdl 函数。

什么时候会出现对全 goroutines、MAXCPUCores、channels 的支持?
再次感谢。

@omac777 ,Go 1.11 的范围是这样的:

Go 代码编译为 WebAssembly 模块并在浏览器中运行,我们可以在 JavaScript 之间来回调用。

忽略有关 *.a 或 *.so 文件或与 C 或 GCC 或 emcc 或 SDL 互操作的任何内容。 这些都不在范围内,也不会起作用。

什么时候会出现对全 goroutines、MAXCPUCores、channels 的支持?

它完全支持 goroutine 和通道(这是 Go 的一部分并且是必需的)。 WebAssembly 仅支持单个核心,如果这就是您所说的MAXCPUCores的话。 这不是 Go 或 Go 的 WebAssembly 支持的限制。

所以你的意思是我不会很快看到这样的事情?
GOARCH=wasm GOOS=js go build -o awesome.wasm.so -buildmode=c-shared foo.go

那么如果我们有 4 核或 20 核的 web 浏览器,go 生成的 wasm 将只在 web 浏览器中使用这些核心之一? 我不明白您如何说这不是 go 或 go webassembly 支持的限制。 您是说这是 WEBASSEMBLY.org 规范本身的限制吗?

@omac777 - 是的,我相信它目前是 WebAssembly 本身的限制,而不是 Go 实现。

@omac777 WASM中的多线程支持正在进行中,在浏览器中发布还需要一段时间。

https://github.com/WebAssembly/threads/blob/master/proposals/threads/Overview.md

所以你的意思是我不会很快看到这样的事情?
GOARCH=wasm GOOS=js go build -o awesome.wasm.so -buildmode=c-shared foo.go

可能在 Go 1.12 中。

对于调用 C/C++ 的 Go,我认为可能可以使用 JavaScript 包装 C 函数,然后使用 Go 1.11 从 Go 调用 JavaScript 包装器。

我知道这不是线程的一部分(也许),但有没有任何文档/教程如何在 go v1.11 中使用 WebAssembly(编译等)?

@SerkanSipahi ,还没有。 但是在发布之前会有文档。

还有这篇文章,仍然相关:
https://blog.gopheracademy.com/advent-2017/go-wasm/

我突然想到,我们没有(IIRC)准确地指定了进入 wasm 模块的export部分的映射(也没有机制)。

我已经提交了#25612。

使用 wasm 目标,请阐明/记录 go 如何:
- 使用 go 将 go 函数导出/导入到 wasm 以供其他语言使用。
-将 sdl2/webgl/qt 链接到 golang 二进制文件
- 捕获所有 sdl2/webgl/qt 事件
- 如果我们处于循环中,则暂时将 cpu 时间放回睡眠状态。 例如
在 emscripten emscripten_sleep(10)

即使成功构建了 output.html,go 工具中的 output.html 文件似乎也无法与 firefox/chrome 一致地成功。 应该做更多工作以确保 output.html 正常工作。 在将其展示为成功之前。

@omac777 ,我们已经完成了上述大部分内容。 但对于其他只是调整的人:

使用 wasm 目标,请阐明/记录 go 如何:
- 使用 go 将 go 函数导出/导入到 wasm 以供其他语言使用。
-将 sdl2/webgl/qt 链接到 golang 二进制文件
- 捕获所有 sdl2/webgl/qt 事件

如上所述,这些都不在 Go 1.11 的范围内。 它不会得到支持、记录,甚至不可能。

- 如果我们处于循环中,则暂时将 cpu 时间放回睡眠状态。 例如

@neelance得到了 JS 和 Go 调度程序之间的回调和互操作,因此常规的time.Sleep和朋友应该按预期工作。

我知道 Go 1.11 不会有任何这些,但上述任何一项将被考虑多远/多长时间。 有些人希望看到 qt 与 go 完全集成,目前的情况是我们依赖第三方来实现该配方/qt,这一切都很好,但有一些限制(目前没有 wasm qt,也没有 qt 64bit arm 目标支持的)。 autocad 有一个使用 emscripten、c++ 和 react 的 windows 和 macos 的 webassembly 解决方案。 我仍然觉得 golang 在某些使用领域仍然受到限制,而不是在可以使用 c++ 的地方。

c++ 的方法有很多功能:
emcc --clear-cache --clear-ports
em++ -v -std=c++1y hello_world_sdl.cpp -s USE_SDL=2 -s USE_SDL_IMAGE=2 EMTERPRETIFY=1 -s EMTERPRETIFY_ASYNC=1 -s WASM=1 -o hello_world_sdl.html

为什么 golang 不能有类似的行为?
更新:我的立场得到纠正。 Golang 不需要“-s”开关,因为 cgo 编译指令嵌入到 go 代码中。

然而,清除缓存和清除端口是一个好主意,因为在迁移到不同的 golang 构建版本(即 go1.9 到 go1.10)时可能会引入错误。 go1.10.3 到 go1.11(当我们迁移到 vgo 生活方式时)。 我最近不得不在 go build 版本之间做一个“go build -a”。
GOARCH=wasm GOOS=js 去 --clear-cache --clear-ports

为什么 golang 不能有类似的行为?
GOARCH=wasm GOOS=js 去 --clear-cache --clear-ports

FWIW,Go 的缓存不需要明确清除正确性。

@neelance - 现在有了回调,我相信基本支持已经完成。 我们应该关闭这个错误还是你有别的想法?

是的,我想我们现在可以关闭它了。 🎉

做得好!!! @neelance

这太棒了,干得好@neelance!

更改https://golang.org/cl/120057提到这个问题: doc/go1.11: mention GOOS/GOARCH values of WebAssembly port explicitly

更改https://golang.org/cl/120575提到这个问题: cmd/dist: skip non-std tests on js/wasm

打开一个关于减小文件大小的问题是否合适(如果可能的话)? 还是在其他地方被追踪?

@matthewp ,如果您愿意,请随时打开特定于 webassembly 的大小错误。 通用的是#6853。

更改https://golang.org/cl/120958提到这个问题: net: re-implement built-in simulated network on JS and NaCl

golang 编译器是否有内置的控制流完整性(CFI)? 我最近浏览了以下内容,以处理 WASM 中的漏洞,这些漏洞是由 clang 编译器内置的 CFI 阻止的:
https://www.fastly.com/blog/hijacking-control-flow-webassembly-program
https://github.com/trailofbits/clang-cfi-showcase/blob/master/cfi_vcall.cpp

只是略读了一下,但在我看来好像帖子说“WebAssembly 不是 JavaScript 等高级语言,而是低级语言,因此如果源语言(C 或 Go)允许,某些类别的错误可能适用。” 那里并不奇怪。 这意味着如果 Go 存在这样的问题,它们也将适用于其他架构,而不仅仅是 WebAssembly。

WebAssembly 主要是为了保护浏览器免受恶意 WebAssembly 代码的侵害。 与其说是在 WebAssembly 实例中提供保证(尽管有一些保证)。 正如@neelance所说,由 LanguageX->WebAssembly 编译器提供任何所需的安全保证。
Go 没有 CFI。 我认为这并不容易——在方法开始的时候,我们已经丢失了 vtable。 我们甚至失去了使用 vtable 的事实。
在存在任何并行性的情况下,Go 很容易受到此漏洞的攻击。 至少目前,WebAssembly Go 端口(以及 WebAssembly,句号)没有并行性,所以这个漏洞利用只是理论上的。 不过,WebAssembly 的人确实计划在某个时候实现并行性。

@randall77这对普通的linux/amd64有何影响? WebAssembly 的风险是否更大?

无论架构如何,风险都是相同的(除了 WebAssembly 还没有线程,因此目前 WebAssembly 实际上为零)。 数据竞赛可用于模拟unsafe ,而无需导入unsafe
很难利用这样的漏洞。 您要么需要链接不受信任的代码,要么以某种方式在现有二进制文件中找到并触发一个小工具,该小工具对接口值进行数据竞争,然后在结果上调用一个方法。

好的,所以如果你的 Go 代码没有数据竞争,那应该没问题。 此外,当使用 WebAssembly 运行不受信任的代码时,您可以确保它无法逃脱 WebAssembly 环境,即使它能够进行数据竞争或仅使用unsafe 。 感谢您提供有趣的见解,并很抱歉这与此问题有点偏离主题。

我从 golang 中检查这种 javascript 用法越多,我就越认为这种感染会降低 golang 代码的质量和长期维护。 让我解释。 这是一个很棒的 wasm golang 应用程序的例子,它做了一些令人印象深刻的眼睛糖果魔术。

https://github.com/stdiopt/gowasm-experiments/blob/master/bouncy/main.go

结果令人印象深刻。 深入研究实际实现它的代码虽然令人失望,因为它要求每次您想从 javascript 端调用某些东西时,它要求您将 javascript 函数的名称或 javascript 值描述为每个轮次的字符串. 因此,golang 编译器无法在编译时检查 javascript 的正确性。 它在运行时是“通过祈祷飞行”。 我更愿意在任何地方看到 golang 函数/变量/类型以进行长期维护,否则在我的拙见中它违背了使用 golang 进行 wasm 的目的。 顺便说一句,我讨厌 javascript 并且一直都有。 太自由了。 为什么这种语言一直存在于网络浏览器中? 答案逃脱了我。

谢谢你的聆听。

我同意使用字符串调用 JS 并不是更好的体验。 也许我们可以从 Web 平台规范 IDL 生成 Go 接口。 缺点是如何跟上规范,因为取决于它将运行的浏览器,API 不可用,而另一方面,随着 Web 平台的发展,新规范不断出现。

@omac777我同意你的看法。 这就是为什么我希望围绕 JS 低级别有不错的 Go 库,这样大多数用户将永远不必直接接触syscall/js 。 类似于syscall包,它很丑,几乎没有人直接使用它。 ;-)

@omac777对于 GopherJS,许多人对各种浏览器 API 使用高级绑定,而不是直接使用低级js包。 我怀疑类似的方法也将在 Wasm 中最受欢迎。 我预计许多 GopherJS 绑定将在同一个包中添加对 Wasm 的支持,并且将根据需要创建新包。

有关参考,请参阅https://github.com/gopherjs/gopherjs/wiki/Bindingshttps://dmitri.shuralyov.com/talks/2016/Go-in-the-browser/Go-in-the-browser。幻灯片#11 (以及以下 4 张幻灯片)和https://github.com/dominikh/go-js-dom/issues/57。

我们还应该考虑到 webassembly 路线图上有很多东西:

https://webassembly.org/docs/future-features/

从长远来看,这将大大改善syscall的故事,比如

直接从 WebAssembly 代码中引用 DOM 和其他 Web API 对象;
直接从 WebAssembly 调用 Web API(传递原语或 DOM/GC/Web API 对象),而不通过 JavaScript 调用; 和
直接从 WebAssembly 代码有效地分配和操作 GC 对象。

无论如何,谢谢@neelance等。 人。 用于实现初始版本。 好棒! 🥇

如果有 DOM 的 Go 实现怎么办?

利用类型系统,可以在 Go 中编写和执行文档和脚本。

然后,可以从 Go DOM 生成代码。

@fractalbach :如果 WebAssembly 的主机绑定由工作组确认并实现,您实际上可以通过 WebAssembly 进行 DOM 操作。 那么使用高级库来抽象 DOM、文档和脚本是合理的。

但在此之前,它并不那么吸引人。

Go WebAssembly:将结构绑定到 JS 引用

https://medium.com/@nlepage/go-webassembly-binding-structures-to-js-references-4eddd6fd4d23

这种方法很有吸引力。 用法类似于结构内的 json 编组/解组。 这使它成为一种易于转移的技能。

缺少的一件事是如何将相同的方法应用于鸭式打字? 我不希望在结构中包含函数声明,而是在其外部以与鸭子类型相同的方式独立。 如果服务存在,它可以使用它。 这样,它很容易修改,而不会影响持有不同所需非函数值的核心结构。 打鸭子的石头!

再次感谢@neelance 所做的所有工作。 非常感谢。
感谢 Nicolas Lepage 先生的观点。 它们确实有助于明确在过渡期间与所有这些 javascript 噪音进行互操作的更好途径,直到直接 wasm 接口完成。

大家好,这是一个有很多人订阅的高流量线程。 对于那些只关心原始问题的人来说,进行这样的一般性讨论并没有什么成果——即让 WebAssembly 支持 Go。

请随时在适当的论坛中继续讨论 - golang-nuts/golang-dev。 或者,如果您有特定的想法,请打开一个新问题。

谢谢你。

此页面是否有帮助?
0 / 5 - 0 等级