diff --git a/exception.go b/exception.go new file mode 100644 index 0000000..8f3a4a2 --- /dev/null +++ b/exception.go @@ -0,0 +1,15 @@ +// Package lua ... +// +// Description : lua ... +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 2025-05-13 14:29 +package lua + +const ( + ErrLuaVmPoolIsEmpty = "lua_vm_pool_is_empty" // 虚拟机实例池为空 + ErrLuaVmScriptRunFail = "lua_vm_script_run_fail" // 虚拟机执行脚本失败 + ErrLuaVmPreCompileScriptNotFound = "lua_vm_pre_compile_script_not_found" // 预编译脚本不存在 + ErrLuaVmPreCompileScriptRunFail = "lua_vm_pre_compile_script_run_fail" // 预编译脚本执行失败 +) diff --git a/go.mod b/go.mod index e4d9a73..237525e 100644 --- a/go.mod +++ b/go.mod @@ -9,6 +9,7 @@ require ( require ( filippo.io/edwards25519 v1.1.0 // indirect + git.zhangdeman.cn/zhangdeman/exception v0.0.0-20250510123912-a0d52fc093ab // indirect github.com/VividCortex/ewma v1.2.0 // indirect github.com/alessio/shellescape v1.4.2 // indirect github.com/aws/aws-sdk-go v1.55.7 // indirect diff --git a/go.sum b/go.sum index 14b8249..9a4fea2 100644 --- a/go.sum +++ b/go.sum @@ -3,6 +3,8 @@ al.essio.dev/pkg/shellescape v1.4.2/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyF cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +git.zhangdeman.cn/zhangdeman/exception v0.0.0-20250510123912-a0d52fc093ab h1:O0XaAKKb8qrjcjewonmKfnRsMFoCfJF+tUv6RfhRe94= +git.zhangdeman.cn/zhangdeman/exception v0.0.0-20250510123912-a0d52fc093ab/go.mod h1:Voc8J4ordx7nuMWpgACXXZULQy7ZIuBzcEIoS8VnDIw= github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA= github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1ow= github.com/VividCortex/ewma v1.2.0/go.mod h1:nz4BbCtbLyFDeC9SUHbtcT5644juEuWfUAUnGx7j5l4= diff --git a/vm.go b/vm.go index 46507a8..2771d8d 100644 --- a/vm.go +++ b/vm.go @@ -8,7 +8,7 @@ package lua import ( - "fmt" + "git.zhangdeman.cn/zhangdeman/exception" libs "github.com/vadv/gopher-lua-libs" luaCompile "github.com/yuin/gopher-lua" "github.com/yuin/gopher-lua/ast" @@ -37,7 +37,7 @@ func InitVM(poolSize int, libPath []string, preComplierScript map[string]string) pathStr += ";" + libDir } pathStr += ";;" - os.Setenv("LUA_PATH", pathStr) + _ = os.Setenv("LUA_PATH", pathStr) if poolSize <= 0 { poolSize = 32 } @@ -47,6 +47,9 @@ func InitVM(poolSize int, libPath []string, preComplierScript map[string]string) pool: make([]*luaCompile.LState, 0), preComplierScript: make(map[string]*luaCompile.FunctionProto), } + for i := 0; i < poolSize; i++ { + VMInstance.pool = append(VMInstance.pool, luaCompile.NewState()) + } for scriptID, scriptContent := range preComplierScript { if err := VMInstance.AddScript(scriptID, scriptContent); nil != err { return err @@ -90,18 +93,19 @@ func (v *VM) RemoveScript(scriptID string) { } // GetVm 获取一个VM实例 -func (v *VM) GetVm(scriptParamList ...ScriptParam) *luaCompile.LState { +func (v *VM) GetVm(scriptParamList ...ScriptParam) (*luaCompile.LState, error) { v.l.Lock() defer v.l.Unlock() if len(v.pool) == 0 { - // 基于libs预导入lua的常用模块 - vm := luaCompile.NewState() - libs.Preload(vm) - // 设置脚本参数 - for _, itemParam := range scriptParamList { - vm.SetGlobal(itemParam.Name, luar.New(vm, itemParam.Value)) - } - return vm + return nil, exception.New(ErrLuaVmPoolIsEmpty, nil, "lua虚拟机实例池为空,请检查是否初始化了虚拟机以及虚拟机实例使用之后是否及时关闭") + /* // 基于libs预导入lua的常用模块 + vm := luaCompile.NewState() + libs.Preload(vm) + // 设置脚本参数 + for _, itemParam := range scriptParamList { + vm.SetGlobal(itemParam.Name, luar.New(vm, itemParam.Value)) + } + return vm*/ } l := v.pool[len(v.pool)-1] // 基于libs预导入lua的常用模块 @@ -111,11 +115,14 @@ func (v *VM) GetVm(scriptParamList ...ScriptParam) *luaCompile.LState { l.SetGlobal(itemParam.Name, luar.New(l, itemParam.Value)) } v.pool = v.pool[:len(v.pool)-1] - return l + return l, nil } // Close 关闭指定虚拟机 func (v *VM) Close(l *luaCompile.LState) { + if nil == l { + return + } l.Close() v.l.Lock() defer v.l.Unlock() @@ -134,16 +141,24 @@ func (v *VM) Shutdown() { func (v *VM) RunPreCompileScript(scriptID string, scriptParamList ...ScriptParam) (*luaCompile.LState, error) { var ( err error + l *luaCompile.LState proto *luaCompile.FunctionProto exists bool ) v.scriptLock.Lock() if proto, exists = v.preComplierScript[scriptID]; !exists { v.scriptLock.Unlock() - return nil, fmt.Errorf("preComplier script %s not found", scriptID) + return nil, exception.New(ErrLuaVmPreCompileScriptNotFound, map[string]any{ + "script_id": scriptID, + }, "预编译脚本不存在") } v.scriptLock.Unlock() - l := v.GetVm(scriptParamList...) + if l, err = v.GetVm(scriptParamList...); nil != err { + return nil, exception.New(ErrLuaVmPreCompileScriptRunFail, map[string]any{ + "script_id": scriptID, + "err_msg": err.Error(), + }, "预编译脚本执行失败") + } lFunc := l.NewFunctionFromProto(proto) l.Push(lFunc) if err = l.PCall(0, luaCompile.MultRet, nil); nil != err { @@ -159,11 +174,19 @@ func (v *VM) RunPreCompileScript(scriptID string, scriptParamList ...ScriptParam // // Date : 18:08 2024/11/14 func (v *VM) Run(script string, scriptParamList ...ScriptParam) (*luaCompile.LState, error) { - l := v.GetVm(scriptParamList...) - if err := l.DoString(script); err != nil { + var ( + err error + l *luaCompile.LState + ) + if l, err = v.GetVm(scriptParamList...); nil != err { + return nil, err + } + if err = l.DoString(script); err != nil { // 直接归还实例 l.Close() - return nil, err + return nil, exception.New(ErrLuaVmScriptRunFail, map[string]any{ + "err_msg": err.Error(), + }, "脚本执行出现异常") } return l, nil }