gopher-lua

A pure-Go Lua 5.1 virtual machine and compiler for embedding a scripting language directly into Go applications.

Library
Go
vv1.1.2
6,979stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
53/100Fair
Development Activity8
Maintenance20
Community84
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
78/100Good
Architecture82
Code Quality78
Innovation80
Learning Curve70

GopherLua is a Lua 5.1 VM and compiler written entirely in Go, with no cgo and no dependency on the reference Lua C implementation. It reimplements the full pipeline of the original Lua toolchain — lexer, parser, bytecode compiler, and a jump-table bytecode interpreter — so Go programs can embed a real scripting language with the same semantics as upstream Lua 5.1 (plus the goto statement from 5.2), while exposing an object-based LValue Go API in place of Lua’s stack-index C API.

Beyond the interpreter itself, GopherLua adds features specific to Go hosts: a channel Lua type and channel.select that mirror Go’s own channel/select concurrency primitives, context.Context-based cancellation so a running script (including inside coroutines) can be timed out or canceled mid-execution, and tunable registry/callstack sizing for running many LState instances efficiently. A documented ecosystem of companion packages (gopher-luar, gluamapper, gluahttp, gluayaml, and others) has grown up around its public API, and the project ships its own glua standalone interpreter binary alongside the importable library.

What You Get

  • Pure-Go Lua 5.1 interpreter - a full lexer, parser, bytecode compiler, and VM with no cgo dependency, so it cross-compiles like any other Go package.
  • Object-oriented Go API - an LValue interface (LNil, LBool, LNumber, LString, LFunction, LUserData, LTable, LChannel) replaces the stack-index C API, trading a little raw speed for Go ergonomics.
  • Goroutine-aware channel type - a first-class Lua channel type plus channel.select that mirror Go’s own channel and select semantics.
  • Context-based cancellation - LState.SetContext lets a running script, including one suspended in a coroutine, be canceled or time out mid-execution.
  • Shareable precompiled bytecode - compile a script once with parse.Parse/Compile into a FunctionProto and run it across many independent LStates.
  • Standalone glua interpreter - a lua-compatible CLI binary (cmd/glua) for running scripts outside of a host Go program.

Common Use Cases

  • Embedding user-scriptable configuration or plugin logic in a Go application without shelling out to a subprocess.
  • Building game or simulation engines where designers write Lua behavior scripts driven by a Go engine core.
  • Running per-tenant or per-request sandboxed scripts, using SkipOpenLibs and context timeouts to bound what untrusted Lua can do.
  • Implementing DSLs or rule engines where business logic changes more often than the surrounding Go binary.

Under The Hood

Architecture GopherLua mirrors the layered design of the reference Lua implementation: ast/*.go defines the syntax tree, parse/lexer.go and a yacc-generated parse/parser.go (from parser.go.y) turn source into that tree, compile.go lowers the AST into bytecode FunctionProtos, and vm.go’s mainLoop/mainLoopWithContext dispatch each instruction through a jumpTable indexed by opcode (inst>>26). state.go’s LState ties it together — callframe stack, registry, globals, and coroutine scheduling — and is the one abstraction nearly every stdlib function and Go-facing API call routes through, so a change to its call/callframe machinery ripples through the whole interpreter.

Tech Stack The core module is pure Go with zero runtime dependencies beyond the standard library and requires no cgo; go.mod only pulls in chzyer/readline for the optional cmd/glua REPL. The build uses a custom preprocessing step (_tools/go-inline) that expands // +inline directives into generated files like vm.go, and CI (GitHub Actions) runs the test suite across Go 1.24/1.25 on Linux, macOS, and Windows with coverage reported to Coveralls.

Code Quality Tests are extensive and script-driven: auxlib_test.go, baselib_test.go, channellib_test.go, oslib_test.go, script_test.go, state_test.go, and table_test.go exercise both the Go API and bundled .lua fixtures (including the upstream _lua5.1-tests suite), all wired into a cross-platform CI matrix. Errors surface explicitly through ArgError/TypeError/RaiseError helpers and Go error returns from DoString/DoFile rather than being swallowed, and Protect: true on CallByParam converts panics into errors instead of crashing the host. Naming is consistent Go style with a deliberate L-prefix convention for Lua-facing types; there is no dedicated linter config beyond gofmt enforced via the Makefile and CI.

API Design The library explicitly chooses an object-based LValue API over Lua’s traditional stack-index C API, documented in the README as a deliberate ergonomics-over-raw-performance tradeoff. An Options struct (RegistrySize, CallStackSize, SkipOpenLibs, IncludeGoStackTrace, etc.) exposes tuning knobs with sane defaults, so lua.NewState() needs zero configuration for basic use. The README’s list of roughly twenty third-party companion packages built on top of this API (gopher-luar, gluamapper, gluahttp, gluayaml, gluasql, and others) is itself evidence of a stable, well-understood public surface other maintainers build against confidently.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search