最近有个需求需要在Go项目里面执行动态脚本,github上有好几个lua执行解释器,但是有很多要不就很久没维护了,要不就没有什么文档,经过几个对比我最后用的是 https://github.com/yuin/gopher-lua。JS解析器用的github.com/robertkrimen/otto。

具体测试代码如下,给有需求的朋友参考。

github地址

package main

import (
	"fmt"
	"github.com/robertkrimen/otto"
	"github.com/yuin/gluamapper"
	"github.com/yuin/gopher-lua"
	"time"
)

//function add(a, b)
//return a+b
//end
var luaCode = `
function testFun(tab)
	result = {}
	result["key"] = "test"
	result["key1"] = "val2"

    if(tab["user"]=="test")then
        result["title"]="good"
    end
    if(tab["os"]=="ios")then
        result["url"]="http://www.google.com"
    else
        result["url"]="http://www.baidu.com"
    end
    
	return result
end
`

func main() {
	dic := make(map[string]string)
	dic["user"] = "test"
	dic["os"] = "ios"
	dic["version"] = "1.0"

	start0 := time.Now()
	count := 10000
	for i := 0; i < count; i++ {
		LuaTest(dic)
	}
	tmp1 := time.Since(start0).Nanoseconds() / 1000 / 1000

	start1 := time.Now()
	for i := 0; i < count; i++ {
		JsTest(dic)
	}
	tmp2 := time.Since(start1).Nanoseconds() / 1000 / 1000
	fmt.Printf("LuaTest : %d,JsTest : %d", tmp1, tmp2)

}

func LuaTest(dic map[string]string) {
	L := lua.NewState()
	defer L.Close()
	if err := L.DoString(luaCode); err != nil {
		panic(err)
	}
	table := L.NewTable()
	for k, v := range dic {
		L.SetTable(table, lua.LString(k), lua.LString(v))
	}

	if err := L.CallByParam(lua.P{
		Fn:      L.GetGlobal("testFun"),
		NRet:    1,
		Protect: true,
	}, table); err != nil {
		panic(err)
	}
	ret := L.Get(-1) // returned value
	L.Pop(1)         // remove received value
	obj := gluamapper.ToGoValue(ret, gluamapper.Option{NameFunc: printTest})
	fmt.Println(obj)
}

func printTest(s string) string {
	return s
}

func JsTest(dic map[string]string) {
	vm := otto.New()
	v, err := vm.Run(`
function testFun(tab) {
	result = {}
	result["key"] = "test"
	result["key1"] = "val2"
 	if(tab["user"]=="test"){
       result["title"]="good"
    }
    if(tab["os"]=="ios"){
        result["url"]="http://www.google.com"
	}else{
        result["url"]="http://www.baidu.com"
    }
	return result
}
`)
	if err == nil {
		fmt.Println(v)
	}
	jsa, err := vm.ToValue(dic)
	if err != nil {
		panic(err)
	}
	result, err := vm.Call("testFun", nil, jsa)


	tmpR, err := result.Export()
	fmt.Println("object: ", tmpR)

}