gopher-lua
Kho lưu trữ: yuin/gopher-lua: GopherLua: VM and compiler for Lua in Go (github.com)
Tài liệu: gopher-lua/README.rst at master · yuin/gopher-lua (github.com)
Giới thiệu
GopherLua là máy ảo và trình biên dịch lua được viết bằng go, sử dụng GoAPI để nhúng script lua vào chương trình Go và thao tác lua bằng GoAPI. Lua là một ngôn ngữ script nhỏ gọn và mạnh mẽ, rất được ưa chuộng trong phát triển game, vì vậy các ứng dụng máy chủ game thường sử dụng nhiều, khi cần tương tác với lua, thư viện này có thể dễ dàng tương tác giữa Go và lua.
Cài đặt
go get github.com/yuin/gopher-luaWARNING
Chỉ hỗ trợ phiên bản Go1.19 trở lên
Bắt đầu nhanh
Tải file lua
package main
import (
"github.com/yuin/gopher-lua"
)
func main() {
L := lua.NewState()
defer L.Close()
if err := L.DoFile("hello.lua"); err != nil {
panic(err)
}
}Hoặc dưới dạng chuỗi trực tiếp
package main
import (
"github.com/yuin/gopher-lua"
)
func main() {
L := lua.NewState()
defer L.Close()
if err := L.DoString(`print("hello")`); err != nil {
panic(err)
}
}Gọi hàm Lua từ Go
package main
import (
"fmt"
"github.com/yuin/gopher-lua"
)
func main() {
L := lua.NewState()
defer L.Close()
// Thực thi script lua
if err := L.DoString(`
function add(a, b)
return a + b
end
`); err != nil {
panic(err)
}
// Gọi hàm lua
if err := L.CallByParam(lua.P{
Fn: L.GetGlobal("add"),
NRet: 1,
Protect: true,
}, lua.LNumber(10), lua.LNumber(20)); err != nil {
panic(err)
}
// Lấy kết quả
ret := L.Get(-1)
fmt.Printf("Kết quả: %v\n", ret)
L.Pop(1) // Loại bỏ kết quả khỏi stack
}Truyền dữ liệu từ Go sang Lua
package main
import (
"github.com/yuin/gopher-lua"
)
func main() {
L := lua.NewState()
defer L.Close()
// Đặt biến cho lua
L.SetGlobal("name", lua.LString("Go Developer"))
L.SetGlobal("version", lua.LNumber(1.0))
if err := L.DoString(`
print("Xin chào từ", name)
print("Phiên bản:", version)
`); err != nil {
panic(err)
}
}Đăng ký hàm Go cho Lua
package main
import (
"fmt"
"github.com/yuin/gopher-lua"
)
func main() {
L := lua.NewState()
defer L.Close()
// Đăng ký hàm Go
L.SetGlobal("goPrint", L.NewFunction(func(L *lua.LState) int {
msg := L.ToString(1)
fmt.Println("Go nhận được:", msg)
return 0
}))
// Gọi từ lua
if err := L.DoString(`
goPrint("Xin chào từ Lua!")
`); err != nil {
panic(err)
}
}Làm việc với Table
package main
import (
"fmt"
"github.com/yuin/gopher-lua"
)
func main() {
L := lua.NewState()
defer L.Close()
// Tạo table
table := L.NewTable()
table.RawSetString("name", lua.LString("test"))
table.RawSetString("value", lua.LNumber(42))
L.SetGlobal("config", table)
if err := L.DoString(`
print("Tên:", config.name)
print("Giá trị:", config.value)
`); err != nil {
panic(err)
}
// Đọc table từ lua
if err := L.DoString(`
data = {
items = {"item1", "item2", "item3"}
}
`); err != nil {
panic(err)
}
data := L.GetGlobal("data").(*lua.LTable)
items := data.RawGetString("items").(*lua.LTable)
items.ForEach(func(key, value lua.LValue) {
fmt.Printf("Item: %v\n", value)
})
}Xử lý lỗi
package main
import (
"fmt"
"github.com/yuin/gopher-lua"
)
func main() {
L := lua.NewState()
defer L.Close()
// Bẫy lỗi
if err := L.DoString(`
error("Đây là một lỗi!")
`); err != nil {
fmt.Println("Bắt được lỗi:", err)
}
// Sử dụng pcall
if err := L.DoString(`
local status, err = pcall(function()
error("Lỗi trong pcall")
end)
print("Status:", status, "Error:", err)
`); err != nil {
fmt.Println("Lỗi:", err)
}
}Module và Package
package main
import (
"github.com/yuin/gopher-lua"
)
func main() {
L := lua.NewState()
defer L.Close()
// Tạo module
mod := L.NewTable()
mod.RawSetString("version", lua.LString("1.0"))
mod.RawSetString("hello", L.NewFunction(func(L *lua.LState) int {
fmt.Println("Xin chào từ module!")
return 0
}))
// Đăng ký module
L.SetGlobal("mymodule", mod)
if err := L.DoString(`
print("Phiên bản module:", mymodule.version)
mymodule.hello()
`); err != nil {
panic(err)
}
}Best Practices
- Quản lý bộ nhớ: Luôn đóng LState bằng defer L.Close()
- Xử lý lỗi: Kiểm tra lỗi sau mỗi lần gọi DoString hoặc DoFile
- Type assertion: Sử dụng type assertion an toàn khi lấy giá trị từ Lua
- Performance: Tái sử dụng LState khi có thể để giảm overhead
- Bảo mật: Không thực thi code lua từ nguồn không đáng tin cậy
Kết luận
GopherLua là một thư viện mạnh mẽ để tích hợp Lua vào ứng dụng Go. Với khả năng gọi hàm qua lại giữa Go và Lua, xử lý table, và đăng ký module, bạn có thể tạo ra các ứng dụng linh hoạt với khả năng script hóa cao.
