• 【Go-Lua】Golang嵌入Lua代码——gopher-lua


    Lua代码嵌入Golang

    Go版本:1.19
    首先是Go语言直接调用Lua程序,并打印,把环境跑通

    package main
    
    import lua "github.com/yuin/gopher-lua"
    
    func main() {
    	L := lua.NewState()
    	defer L.Close()
    	// go
    	err := L.DoString(`print("go go go!")`)
    	if err != nil {
    		return
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    Lua的stdout可以直接转到go的stdout里,不过只调用打印一下没用意义,最重要的是函数调用

    Go调用Lua的函数

    Go调用Lua的函数最常用,Lua程序里定义函数和数据的处理方式,Go通过HTTP或者TCP获取到数据后,调用Lua的函数对数据处理,处理后,结果返回到Go语言,写入数据库或进行其他处理。

    • Lua代码
      在这里插入图片描述
    function add(a,b)
        return a+b
    end
    
    • 1
    • 2
    • 3

    Lua支持多个参数和多个返回值,参数好办,用lua.LNumber(123)

    类型有:

    • LTNil
    • LTBool
    • LTNumber
    • LTString
    • LTFunction
    • LTUserData
    • LTThread
    • LTTable
    • LTChannel

    返回值个数也可以是多个,调用CallByParam的时候,NRet就是返回参数个数,Fn是要调用的全局函数名,Protecttrue时,如果没找到函数或者出错不会panic,只会返回err。

    调用完成后,要以压栈的方式,一个一个取回返回值ret := L.Get(-1)

    • Go代码
      在这里插入图片描述
    package main
    
    import (
    	"fmt"
    
    	lua "github.com/yuin/gopher-lua"
    )
    
    func main() {
    	L := lua.NewState()
    	defer L.Close()
    	// go
    	err := L.DoFile("main.lua")
    	if err != nil {
    		fmt.Print(err.Error())
    		return
    	}
    	err = L.CallByParam(lua.P{
    		Fn:      L.GetGlobal("add"),
    		NRet:    1,
    		Protect: true,
    	}, lua.LNumber(1), lua.LNumber(2))
    	if err != nil {
    		fmt.Print(err.Error())
    		return
    	}
    	ret := L.Get(-1)
    	// 如果是2个返回值, NRet改为2
    	// 	ret2 := L.Get(2)
    	//  L.Pop(2)
    	L.Pop(1)
    	res, ok := ret.(lua.LNumber)
    	if ok {
    		fmt.Println(res)
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    Lua调用Go的函数

    Lua调用Go语言的函数就没那么常用,因为虚拟机在Go语言程序里,需要传递数据直接通过Go的SetGlobal或函数调用就可以了。

    不过仍然有一种应用场景需要Lua调用Go语言的函数,例如数据处理过程中,需要发送一个异步HTTP请求,或者把数据插入到MySQL或者Redis,就可以调用Go的HTTP请求函数或数据库处理函数。

    • Lua
    print(add(10,20))
    
    • 1
    • Go
    package main
    
    import (
    	"fmt"
    
    	lua "github.com/yuin/gopher-lua"
    )
    
    func Add(L *lua.LState) int {
    	// 获取参数
    	arg1 := L.ToInt(1)
    	arg2 := L.ToInt(2)
    
    	ret := arg1 + arg2
    
    	// 返回值
    	L.Push(lua.LNumber(ret))
    	// 返回值的个数
    	return 1
    }
    
    func main() {
    	L := lua.NewState()
    	defer L.Close()
    
    	// 注册全局函数
    	L.SetGlobal("add", L.NewFunction(Add))
    
    	// go
    	err := L.DoFile("main.lua")
    	if err != nil {
    		fmt.Print(err.Error())
    		return
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    LuaTable转为GoStruct

    package main
    
    import (
    	"fmt"
    
    	"github.com/yuin/gluamapper"
    	lua "github.com/yuin/gopher-lua"
    )
    
    func main() {
    	type Role struct {
    		Name string
    	}
    
    	type Person struct {
    		Name      string
    		Age       int
    		WorkPlace string
    		Role      []*Role
    	}
    
    	L := lua.NewState()
    	if err := L.DoString(`
    		person = {
    		  name = "Michel",
    		  age  = "31", -- weakly input
    		  work_place = "San Jose",
    		  role = {
    			{
    			  name = "Administrator"
    			},
    			{
    			  name = "Operator"
    			}
    		  }
    		}
    `); err != nil {
    		panic(err)
    	}
    	var person Person
    	if err := gluamapper.Map(L.GetGlobal("person").(*lua.LTable), &person); err != nil {
    		panic(err)
    	}
    	fmt.Printf("%s %d", person.Name, person.Age)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
  • 相关阅读:
    链表(1)
    QT界面设计随笔
    shell编程(五):大小写转换
    国产化系统中遇到的视频花屏、卡顿以及延迟问题的记录与总结
    mongodb的基本知识点
    图像处理方面的笔试面试题目及回答总结整理1~20
    SpringBoot对Filter过滤器中的异常进行全局处理
    工具篇 | Gradle入门与使用指南 - 附Github仓库地址
    java不同类加载器重复加载一个类
    RS485 光照度传感器 pc串口工具调试设备 亲身体验
  • 原文地址:https://blog.csdn.net/xuehu96/article/details/126613678