前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >教你把go rust wasm结合在一起装逼

教你把go rust wasm结合在一起装逼

作者头像
sealyun
发布2021-12-15 19:12:50
1.4K0
发布2021-12-15 19:12:50
举报
文章被收录于专栏:sealyunsealyun

| wasm将火

如果你还没意识到,那抓紧学习起来了,正如docker创始人的说法,wasm早出现几年就没docker啥事了。那即使现在出来也不晚。

Polkadot的核心runtime也用wasm跑的,包括区块链领域的新兴合约都统一选择用wasm。云原生领域serverless 函数计算与网络方面也都有相关实践,一切的一切似乎都朝着一个目标在走,希望最终可以天下大势分久必合。

之前我用rust编译成wasm写前端,基本需求都能满足,路由、双向绑定、数据传输、模块等都可以实现。

所以真感觉rust+wasm快打遍天下无敌手了。

那总有那么些场景需要结合一下的,比如[sealer](https://github.com/alibaba/sealer)中希望用rust优化镜像分发的性能,但是整个sealer大部分都是go写的,全改成rust不实际,而且目前还是go统治着云原生领域,很多代码拿来主义很方便。但是rust实现的一些存储能力又非常优秀想去集成怎么办?

牛逼的想法诞生:

用golang去调用rust,调用命令行这种又low又没有技术含量的事我肯定不会去做。而且一旦调用命令行你让用户下载两个二进制?不符合我让用户极简的设计。

所以,用rust写,编译成wasm,使用golang去调用,并且直接把wasm打到golang二进制中去。

| rust编译成wasm

安装一下wasm工具链:

代码语言:javascript
复制
rustup target add wasm32-unknown-unknown

wasm-gc可以用来压缩wasm输出文件,移除不需要的一些东西

代码语言:javascript
复制
cargo install wasm-gc

创建一个库

代码语言:javascript
复制
cargo new add --lib

改一下Cargo.toml把依赖加一下

代码语言:javascript
复制
➜ test cat add/Cargo.toml 
[package]
name = "add"
version = "0.1.0"
authors = ["中弈"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[lib]
crate-type = ["cdylib"]

写点代码,这里就是一个相加的函数

代码语言:javascript
复制
➜ test cat add/src/lib.rs 
#[no_mangle]
pub extern "C" fn sum(x: i32, y: i32) -> i32 {
 x + y
}

编译成wasm

代码语言:javascript
复制
cargo build --target wasm32-unknown-unknown --release

然后我们就能看到产物了

代码语言:javascript
复制
add/target/wasm32-unknown-unknown/release/add.wasm

| 使用golang调用wasm

这里需要用 github.com/wasmerio/wasmer-go/wasmer

代码语言:javascript
复制
package main

import (
 "fmt"
"io/ioutil"

 wasmer "github.com/wasmerio/wasmer-go/wasmer"
)

func main() {
 wasmBytes,_:= ioutil.ReadFile("add/target/wasm32-unknown-unknown/release/add.wasm")

 engine := wasmer.NewEngine()
 store := wasmer.NewStore(engine)

 // Compiles the module
 module, _ := wasmer.NewModule(store, wasmBytes)

 // Instantiates the module
 importObject := wasmer.NewImportObject()
 instance, _ := wasmer.NewInstance(module, importObject)

 // Gets the `sum` exported function from the WebAssembly instance.
 sum, _ := instance.Exports.GetFunction("sum")

 // Calls that exported function with Go standard values. The WebAssembly
 // types are inferred and values are casted automatically.
 result, _ := sum(5, 37)

 fmt.Println(result) // 42!
}

首先读取wasm文件,然后用GetFunction获取到我们在rust里面定义的函数名即可,然后就可以直接调用函数了。

运行一下:

代码语言:javascript
复制
➜ test go build && ./test 
42

| wasm打包到golang二进制中

这里我们用 github.com/go-bindata/go-bindata

代码语言:javascript
复制
go get -u github.com/go-bindata/go-bindata/...

把wasm生成一个add.go文件

代码语言:javascript
复制
go-bindata -o add.go add/target/wasm32-unknown-unknown/release/add.wasm

然后稍微改一行我们的golang代码,把从文件中读取直接写成调用Asset函数即可

代码语言:javascript
复制
wasmBytes,_:= Asset("add/target/wasm32-unknown-unknown/release/add.wasm")

其它都不用动

代码语言:javascript
复制
➜ test go build && ./test
42

此时wasm已经在test二进制中,一个二进制丢出去就好了

注意把wasm编译进去前后二进制大小并没有发生什么变化都是2.9M,这就是wasm的优势之一,编译产物非常小

| 总结

wasm的出现让各种语言之间的互操作性成为可能,这就是标准的好处。还可以用各种编程语言写浏览器应用,比如用rust/c++写前端,把游戏引擎运行在浏览器中。

wasm的强大让他不仅可以跑在浏览器中,wasi可以很好的处理系统调用,这样系统中的绝大多数应用都可以编译成wasm,比如nginx编译成wasm之后也就几百KB。

函数计算领域快速扩容非常依赖编译产物的大小,所以python js这些脚本语言就有一些优势,用java这种拖着虚拟机的就很尴尬。golang rust c/c++这种编译型语言有了wasm之后去写函数计算应用也就成为可能,关键是函数就可以不用搞那么多执行引擎了,只需要一个wasm执行器,整个系统架构变简单了。

所以感觉下一个颠覆式革命非常有可能由wasm引爆,云提供商值得去在serverless+wasm上梭哈。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-12-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 sealyun 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • | wasm将火
  • | rust编译成wasm
  • | 使用golang调用wasm
  • | wasm打包到golang二进制中
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档