Go调用JS脚本

Go调用JS脚本

Goja

项目地址:goja

基本使用

func main(){
    vm := goja.New()
    val, err := vm.RunString(`
        2+2
    `)
    if err != nil {
        log.Fatalln(err)
    }
    if v, ok := val.Export().(int64); ok {
        fmt.Println(v)
    }
}

传值到 js 中

func main(){
    vm := goja.New()
    vm.Set("println", func(args ...interface{}) {
        fmt.Println(args)
    })
    _, err := vm.RunString(`
        println("Hello world")
    `)
    if err != nil {
        log.Fatalln(err)
    }
}

还可以使用 vm.ToValue()

func main(){
    vm := goja.New()
    vm.Set("println", func(args ...interface{}) {
        fmt.Println(args)
    })
    _, err := vm.RunString(`
    function log(param){
        println(param)
    }
    `)
    if err != nil {
        log.Fatalln(err)
    }
    // 获取 js 中的函数。
    callbal, ok := goja.AssertFunction(vm.Get("log"))
    if ok {
        callbal(goja.Undefined(), vm.ToValue(map[string]interface{}{
            "name": "xiaoming",
            "age":  18,
        }))
    }
}

从 js 中导出函数

func main(){
    vm := goja.New()
    _, err := vm.RunString(`
        function f(param){
            return +param+2
        }
    `)
    if err != nil {
        log.Fatalln(err)
    }
    var f func(val int) int
    err = vm.ExportTo(vm.Get("f"), &f) // 第二个参数必须是指针
    if err != nil {
        log.Fatalln(err)
    }
    fmt.Println(f(40))
}

匹配结构体字段和方法名称

有两个方法:TagFieldNameMapperUncapFieldNameMapper

type tagtest struct {
    Test string `json:"test"`
}

func (tagtest) Method(s string) string {
    return s
}

func tag() {
    vm := goja.New()
    t := tagtest{
        Test: "passed",
    }
    vm.SetFieldNameMapper(goja.TagFieldNameMapper("json", true))
    vm.Set("t", t)
    val, err := vm.RunString(`
        t.test + " and " + t.method("passed too")
    `)
    if err != nil {
        log.Fatalln(err)
    }
    fmt.Println(val.Export())
}

type uncaptest struct {
    Test string 
}

func (uncaptest) Method(s string) string {
    return s
}

func uncap(){
    vm := goja.New()
    u := uncaptest{
        Test: "passed",
    }
    vm.SetFieldNameMapper(goja.UncapFieldNameMapper())
    vm.Set("u", u)
    val, err := vm.RunString(`
        u.test + " and " + u.method("passed too")
    `)
    if err != nil {
        log.Fatalln(err)
    }
    fmt.Println(val.Export())
}

异常

// go 中捕获 js 异常
func catch() {
    vm := goja.New()
    _, err := vm.RunString(`
    throw("Test");
    `)
    if jserr, ok := err.(*goja.Exception); ok {
        if jserr.Value().Export() != "Test" {
            panic("wrong value")
        }
    } else {
        panic("wrong type")
    }
}
// js 中捕获 go panic
func catch2() {
    vm := goja.New()
    test := func() {
        panic(vm.ToValue("Error"))
    }
    vm.Set("test", test)
    _, err := vm.RunString(`
            try{
                test()
            }catch(e){
                if (e !== "Error") {
                    throw e;
                }
            }
    `)
    if err != nil {
        panic(err)
    }
}

中断

func TestInterrupt(t *testing.T) {
    const SCRIPT = `
    var i = 0;
    for (;;) {
        i++;
    }
    `

    vm := goja.New()
    time.AfterFunc(200*time.Millisecond, func() {
        vm.Interrupt("halt")
    })

    _, err := vm.RunString(SCRIPT)
    if err == nil {
        t.Fatal("Err is nil")
    }
    // err is of type *InterruptError and its Value() method returns whatever has been passed to vm.Interrupt()
}

 上一篇
angular学习笔记 angular学习笔记
angular学习笔记学习资源:官网 核心概念和架构Angular 是一个用 HTML 和 TypeScript 构建客户端应用的平台与框架。 Angular 本身就是用 TypeScript 写成的。它将核心功能和可选功能作为一组 Typ
2020-12-22
下一篇 
如何优雅的关闭channel 如何优雅的关闭channel
如何优雅的关闭channel关闭channel会出现的问题1.在没有改变 channel 的状态情况下,没有简单的方法来检查通道是否关闭。 2.关闭已经关闭的 channel 会造成 panic 。 3.向一个已经关闭的 channel 中
2020-12-08
  目录