最新消息称 WebAssembly 成为 W3C 标准。WebAssembly 也正式抵达了 1.0 版本,它已获得了主流浏览器 Firefox、Chrome、Safari 和 Edge 的支持。
学习一下 go关于WebAssembly: https://github.com/golang/go/wiki/WebAssembly
这里提到了命令行运行go代码的工具,这样就不需要另外建立一个web服务器。
// install goexec: go get -u github.com/shurcooL/goexec
$ goexec ‘http.ListenAndServe(:8080
, http.FileServer(http.Dir(.
)))’
其它:浏览器中的操作系统 https://bellard.org/jslinux/
因为WebAssembly是新技术,所以golang也在不断改进,原来的js.NewCallback已经换为js.FuncOf。看下面的例子:
//从go中为js定义一个函数
package main
import (
"fmt"
"syscall/js"
)
func add(this js.Value, i []js.Value) interface{} {
js.Global().Set("output", js.ValueOf(i[0].Int()+i[1].Int()))
fmt.Printf("%v\n", js.ValueOf(i[0].Int()+i[1].Int()))
return nil
}
func registerCallbacks() {
js.Global().Set("add", js.FuncOf(add))
}
func main() {
//c := make(chan struct{}, 0)
println("Go WebAssembly Initialized")
registerCallbacks()
//<-c
select{}
}
原来的方式类似于:
func foo( args []js.Value) {
fmt.Println("hellow wasm")
fmt.Println(args)
}
func main() {
js.Global().Set("foo", js.NewCallback(foo))
select {}
}
所以注意定义和注册时的不同:1.参数部份的修改 2.返回值及类型
原来网上一些开源的库也需要一并修改。我的go版为1.13.5,我是追新党。
上例中定义的add函数,只是在js中注册,并未调用。可以在html中调用,或者直接在控制台add(…)即可看出反馈结果。
在html源代码中并不能看到go或者说是wasm中的定义等,这或许也算有利于代码安全吧。以前为了获取一些资源,会去分析一些javascript代码,搞懂作者的调用机制,从而绕过。
示例:GO获取DOM元素,操作标签属性
在html中添加一个div,供wasm调用。
package main
import (
"syscall/js"
)
func setDivRedColor(this js.Value, args []js.Value) interface{} {
// 获取DOM元素, 进行设置属性, call方法为调用js方法
js.Global().Get("document").Call("getElementById", "div").Set("style", "width: 300px; height: 300px; background-color: red")
// 注意, 此处设置style的时候, 是会覆盖掉html中的style设置
return nil
}
func main() {
js.Global().Set("setDivRedColor", js.FuncOf(setDivRedColor))
select {}
}
关键就是这一句,当然原本就没几句
js.Global().Get(“document”).Call(“getElementById”, “div”).Set(“style”, “width: 300px; height: 300px; background-color: red”)
我猜: js.Global() 获取js所有资源 js.Global().Get(“document”) 获取到IE的内容部份 js.Global().Get(“document”).Call(“getElementById”, “div”) IE内容中,通过ID获取到DIV js.Global().Get(“document”).Call(“getElementById”, “div”).Set() 设置目标的相关属性
继续一个交互示例:
在html中
<input type="text" id="v1" />
<input type="text" id="v2" />
<button onClick="add('v1', 'v2', 'result');" id="addButton">Add</button>
<input type="text" id="result" />
在go中
func add(this js.Value, i []js.Value) interface{} {
value1 := js.Global().Get("document").Call("getElementById", i[0].String()).Get("value").String()
value2 := js.Global().Get("document").Call("getElementById", i[1].String()).Get("value").String()
int1, _ := strconv.Atoi(value1)
int2, _ := strconv.Atoi(value2)
js.Global().Get("document").Call("getElementById", i[2].String()).Set("value", int1+int2)
return nil
}
换个姿势给myBtn定义一个click事件
cb := js.FuncOf(func(this js.Value,ev []js.Value) interface{} {
println("click...")
return nil
})
js.Global().Get("document").Call("getElementById", "myBtn").Call("addEventListener", "click", cb)
而html可以很简单添加click即可
在上例中作一些修改,html添加
Add1
加一个javascript:
function add1(t1,t2,t3) {
var ret = subtract(document.getElementById(t1).value,document.getElementById(t2).value);
document.getElementById(t3).value = ret;
}
意思是想在golang中执行功能,而html负责与前台有关的调用,无需理会前台各个关系。
在go中执行功能,返回执行结果。
func Subtract(this js.Value, i []js.Value) interface{} {
int1, _ := strconv.Atoi(i[0].String())
int2, _ := strconv.Atoi(i[1].String())
//return strconv.Itoa(int1+int2)
return int1+int2
}
js.Global().Set("subtract", js.FuncOf(Subtract))
之前试用 string(i[0].Int()) 或者 strconv.Itoa(i[0].Int()) 或者 i[0].Int() 都是错误的,提示panic: syscall/js: call of Value.Int on string。 必须String()后,再Atoi转换为整型进行运算。