现代地图数据量更大,二三维渲染要求更高,必须要借助于WebAssembly提升性能。
GO是一种只需要半天学习就能上手的语言,跨平台编译也极其容易,转换为WebAssembly的方式也极简单,因此应从GO入手高性能WebGIS。
至于怎么把Go的代码转换成WebAssembly,网上的文章经常会写到这类命令:
GOOS=js GOARCH=wasm go build -o ../../json.wasm
对应Windows下用powershell设置的方法为先后执行以下两句:
$env:GOOS="js"
$env:GOARCH="wasm"
编译:
go build -o test.wasm testgoroutine.go
GOOS实际指编译后的代码所运行的操作系统,要在浏览器运行就是js
GOARCH指编译后代码要运行的平台,这里是wasm
在命令行中运行:go env可查看GOOS和GOARCH的参数。
在GO安装目录的misc目录下有wasm_exec.js文件。
最简单的调用示例代码:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Go wasm</title>
</head>
<body>
<script src="wasm_exec.js"></script>
<script>
async function run(fileUrl) {
try {
const file = await fetch(fileUrl);
const buffer = await file.arrayBuffer();
const go = new Go();
const { instance, module} = await WebAssembly.instantiate(buffer, go.importObject);
console.log(instance, module);
go.run(instance);
} catch (err) {
console.error(err);
}
}
setTimeout(() => run("./test.wasm"));
</script>
</body>
</html>
go示例代码:
package main
import (
"fmt"
"time"
)
func say(s string) {
for i := 0; i < 5; i++ {
time.Sleep(100 * time.Millisecond)
fmt.Println(s)
}
}
func main() {
go say("world")
say("123")
}
如何将go的函数暴露给js,并通过js传递参数?有几个关键点:
1.go编译器内置有syscall/js这个库,可以用来把go的函数暴露给js,主要通过js.Global().Set("fibFunc", js.FuncOf(fibFunc))
。
2.通过 args
获取参数。
3.计算结果要用js.ValueOf
包装后再传回js才能被js使用。
4.js中要先go.run(instance);
实例化整个wasm文件内容才能调用其它函数。
go的代码:
package main
import "syscall/js"
// 参考:https://geektutu.com/post/quick-go-wasm.html
func fib(i int) int {
if i == 0 || i == 1 {
return 1
}
return fib(i-1) + fib(i-2)
}
func fibFunc(this js.Value, args []js.Value) interface{} {
return js.ValueOf(fib(args[0].Int()))
}
func main() {
done := make(chan int, 0)
js.Global().Set("fibFunc", js.FuncOf(fibFunc))
<-done
}
.html文件的代码:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Go wasm</title>
</head>
<body>
<script src="wasm_exec.js"></script>
<script>
async function run(fileUrl) {
try {
const file = await fetch(fileUrl);
const buffer = await file.arrayBuffer();
const go = new Go();
const { instance, module} = await WebAssembly.instantiate(buffer, go.importObject);
console.log(instance, module);
go.run(instance);
console.log(fibFunc(4));
} catch (err) {
console.error(err);
}
}
setTimeout(() => run("./test.wasm"));
</script>
</body>
</html>
网友评论