Lua code embedded in Golang
Go version: 1.19
First, the Go language directly calls the Lua program and prints it to run through the environment
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
}
}
Lua's stdout can be directly transferred to go's stdout, but it's useless to just call and print, the most important thing is the function call
Go calls Lua functions
Go calls Lua functions most often. The Lua program defines the processing methods of functions and data. After Go obtains data through HTTP or TCP, it calls Lua functions to process the data. After processing, the results are returned to the Go language and written into the database or Do other processing.
- Lua code
function add(a,b)
return a+b
end
Lua supports multiple parameters and multiple return values, the parameters are easy to handle, uselua.LNumber(123)
The types are:
- LTNil
- LTBool
- LTNumber
- LTString
- LTFunction
- LTUserData
- LTThread
- LTTable
- LTChannel
The number of return values can also be multiple. When calling CallByParam
, NRet
it is the number of return parameters. Fn is the name of the global function to be called. Protect
Iftrue
the function is not found or an error occurs, it will not panic, and only err will be returned.
After the call is completed, the return value should be retrieved one by one by pushing the stackret := L.Get(-1)
- Go code
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)
}
}
Lua calls Go functions
SetGlobal
It is not so common for Lua to call Go language functions, because the virtual machine needs to transfer data directly through Go or function calls in the Go language program .
However, there is still an application scenario that requires Lua to call functions in the Go language. For example, during data processing, if you need to send an asynchronous HTTP request, or insert data into MySQL or Redis, you can call Go’s HTTP request function or database processing function.
- Lua
print(add(10,20))
- 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
}
}
LuaTable to 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)
}