大家好,我是建宇。最近因为各种莫名其妙的原因,对WebAssembly的接触比较多。虽然很多博主之前都看过写过各种文章,但总觉得自己少了一些品味。于是今天整理了一个版本,开始和大家一起学习。先从一张经典图说起:什么是WebAssembly?以下是Mozilla在MDN上给出的定义:WebAssembly(缩写:Wasm)是一种可以在现代网络浏览器中运行的新编码方式——它是一种低级的类汇编语言,具有紧凑的二进制格式,运行于接近本机的性能,并为C/C++等语言提供编译目标,以便它们可以在Web上运行。它还被设计为与JavaScript共存,允许两者一起工作。Wasm官网的重点是它是一种基于栈的虚拟机的二进制指令格式。设计为编程语言的可移植编译目标。能够在网络上部署客户端和服务器应用程序。新的编码方法可以在浏览器中运行。可以以接近本机的性能运行。可以跨语言,如:C/C++;可以与JavaScript共存。看起来像一个不错的新跨平台玩具。哪家最早基于asm.js的特性集(Javascript的严格子集、静态类型、取消垃圾回收机制等)开发了WebAssembly1.0。后续的WebAssembly2.0根据新的标准进行了进一步的扩展和发展。WebAssembly的开发团队分别来自Mozilla、Google、Microsoft和Apple,代表了四大网络浏览器Firefox、Chrome、MicrosoftEdge和Safari。一些重要的时间表:2015年首次发布WebAssembly,Unity的AngryBots在上述四大浏览器中的演示。2017年3月,首次发布WebAssemblyMVP版本。预览版结束,正式发布,可以理解为1.0。2018年2月,WebAssembly工作组(WebAssemblyWorkingGroup)发布了三个核心规范,JavaScript接口和WebAPI。公共工作草案。2019年,Chrome75发布,默认启用WebAssembly线程。2022年6月,WebAssembly2.0将开始发布。几个大厂都派人一起做。它比较新,最近几年才开始得到更多的支持。目前还处于WebAssembly2.0阶段,还在开发阶段。1.0和2.0的区别之一直观上,1.0和2.0最大的区别是1.0的主要目标是在所有主流浏览器中运行WebAssembly。据统一统计,截至2022年10月,96%的已安装浏览器支持WebAssembly(1.0版),基本实现全覆盖。是什么让WebAssembly焕发青春(2.0):可以使用WASI(WebAssemblySystemInterfac)的模块化系统接口,中间产物.wasm可以实现各种语言的集合和相互融合。从WebAssembly2.0开始,界限就更大了,目标完全是一种可移植、安全的高级语言。有望应用于浏览器、各种编程语言、各种系统。有一种JVM的感觉:快速了解WebAssembly的背景后,快去吧。让我们深入了解一下Go中的WebAssembly发生了什么以及它是如何使用的。Go目前有两种使用WebAssembly的方式。第一种是使用syscall/js标准库,它几乎不支持WebAssembly1.0。代码如下:packagemainimport"syscall/js"funcmain(){alert:=js.Global().Get("alert")alert.Invoke("Mybrainisfryingfish!")}编译命令:$GOOS=jsGOARCH=wasmgobuild-ojianyu.wasm然后在JS中使用对应的WebAssembly调用。第二种使用方式是使用开源库tinygo-org/tinygo,它基于LLM,支持WebAssembly1.0/2.0(WASM/WASI)。tinygobrew安装方法:$brewtaptinygo-org/tools$brewinstalltinygo如果安装成功,执行tinygoversion可以看到版本信息。Gowasm代码如下:import(figure"github.com/common-nighthawk/go-figure")//exportHelloWorldfuncHelloWorld(){myFigure:=figure.NewFigure("HelloWorld","",true)myFigure.Print()}funcmain(){}编译命令:tinygobuild-omodule.wasm-targetwasi。运行成功后会在相应目录下编译出module.wasm二进制文件,供其他平台和语言使用。如果要在Go或其他语言中调用生成的.wasm,需要找到对应的符合WASI的库和规则。下面是Gowasmer-go调用.wasm的代码:import("fmt""io/ioutil"wasmer"github.com/wasmerio/wasmer-go/wasmer")funcmain(){wasmBytes,_:=ioutil.ReadFile("module.wasm")store:=wasmer.NewStore(wasmer.NewEngine())模块,_:=wasmer.NewModule(store,wasmBytes)wasiEnv,_:=wasmer.NewWasiStateBuilder("wasi-program")。//根据自己的实际情况选择//??Argument("--foo").//环境(“ABC”,“DEF”)。//映射目录("./",".").Finalize()importObject,err:=wasiEnv.GenerateImportObject(store,module)check(err)实例,err:=wasmer.NewInstance(module,importObject)check(err)start,err:=instance.Exports.GetWasiStartFunction()check(err)start()HelloWorld,err:=instance.Exports.GetFunction("HelloWorld")检查(err)结果,_:=HelloWorld()fmt.Println(result)}funccheck(eerror){ife!=nil{panic(e)}}运行成功后会输出"HelloWorld"Go标准库syscall/js标准库只支持WebAssembly1。0,只能应用于JS相关场景,不能被其他语言集成。其中tinygo实现了WASI,通过WASI的标准接口与其他平台语言集成。但是tinygo并不支持所有的Go语法特性,具体请参考Go语言特性。这需要特别注意,因为不同的语言对WebAssembly(WASI)的支持程度不同。WebAssembly在其他应用场景中流行的另一个重要因素是它可以在各种云原生组件上集成使用,进一步扩展场景。例如,在Envoy和Istio上,您可以使用wasm轻松地将自定义过滤器集成到Envoy中,以增强Envoy代理的功能。总结今天我们快速了解了WebAssembly的背景,快速介绍了Go,并了解了扩展场景。WebAssembly虽然是一个新造的轮子,但也号称是借助WASI集成集成的。但实际上现在各个语言对WebAssembly的支持程度是不一样的。Go官方本身提供的标准库维护得不好,WASI的问题也没有继续推进。即使在其他语言的互通中,也或多或少会出现阻塞而无法应用的问题。也许,还需要3~5年?但是这么多语言的库维护是可以长期迭代维护的。也是更大的问题。文章持续更新中。可以微信搜索【脑补炸鱼】阅读。本文已收录在GitHubgithub.com/eddycjy/blog中。学习Go语言可以看Go学习地图和路线。欢迎星星提醒。Go书系列Go语言入门系列:初探Go项目实战Go语言编程之旅:深入使用Go做项目Go语言设计哲学:理解Go的Why与设计思维Go语言进阶之旅:走得更远Go源码推荐阅读醒醒吧,以后就没有Go2了!Go1.20的那些事:PGO、编译速度、错误处理等新特性,你知道多少?向斯威夫特学习?Go考虑简单的字符串插值特性
