• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

.github/H29-May-2021-

_glua-tests/H29-May-2021-

_lua5.1-tests/H29-May-2021-

_tools/H29-May-2021-

ast/H29-May-2021-

cmd/glua/H29-May-2021-

parse/H29-May-2021-

pm/H29-May-2021-

.travis.ymlH A D29-May-2021493

LICENSEH A D29-May-20211.1 KiB

MakefileH A D29-May-2021241

README.rstH A D29-May-202128.4 KiB

_state.goH A D29-May-202146.6 KiB

_vm.goH A D29-May-202125.2 KiB

alloc.goH A D29-May-20212.1 KiB

auxlib.goH A D29-May-20219.1 KiB

auxlib_test.goH A D29-May-20217.7 KiB

baselib.goH A D29-May-202111.4 KiB

channellib.goH A D29-May-20213.7 KiB

channellib_test.goH A D29-May-20216.7 KiB

compile.goH A D29-May-202144 KiB

config.goH A D29-May-2021746

coroutinelib.goH A D29-May-20211.9 KiB

debuglib.goH A D29-May-20213.3 KiB

function.goH A D29-May-20214 KiB

go.modH A D29-May-2021300

go.sumH A D29-May-2021820

iolib.goH A D29-May-202115.5 KiB

linit.goH A D29-May-20211.6 KiB

loadlib.goH A D29-May-20212.8 KiB

mathlib.goH A D29-May-20214.5 KiB

opcode.goH A D29-May-202113.3 KiB

oslib.goH A D29-May-20214.4 KiB

package.goH A D29-May-2021266

script_test.goH A D29-May-20212.9 KiB

state.goH A D29-May-202150.8 KiB

state_test.goH A D29-May-202118.5 KiB

stringlib.goH A D29-May-20219.4 KiB

table.goH A D29-May-20218.1 KiB

table_test.goH A D29-May-20214.9 KiB

tablelib.goH A D29-May-20211.8 KiB

testutils_test.goH A D29-May-20212.1 KiB

utils.goH A D29-May-20215.1 KiB

value.goH A D29-May-20217.3 KiB

vm.goH A D29-May-202144.8 KiB

README.rst

1
2===============================================================================
3GopherLua: VM and compiler for Lua in Go.
4===============================================================================
5
6.. image:: https://godoc.org/github.com/yuin/gopher-lua?status.svg
7    :target: http://godoc.org/github.com/yuin/gopher-lua
8
9.. image:: https://travis-ci.org/yuin/gopher-lua.svg
10    :target: https://travis-ci.org/yuin/gopher-lua
11
12.. image:: https://coveralls.io/repos/yuin/gopher-lua/badge.svg
13    :target: https://coveralls.io/r/yuin/gopher-lua
14
15.. image:: https://badges.gitter.im/Join%20Chat.svg
16    :alt: Join the chat at https://gitter.im/yuin/gopher-lua
17    :target: https://gitter.im/yuin/gopher-lua?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
18
19|
20
21
22GopherLua is a Lua5.1 VM and compiler written in Go. GopherLua has a same goal
23with Lua: **Be a scripting language with extensible semantics** . It provides
24Go APIs that allow you to easily embed a scripting language to your Go host
25programs.
26
27.. contents::
28   :depth: 1
29
30----------------------------------------------------------------
31Design principle
32----------------------------------------------------------------
33
34- Be a scripting language with extensible semantics.
35- User-friendly Go API
36    - The stack based API like the one used in the original Lua
37      implementation will cause a performance improvements in GopherLua
38      (It will reduce memory allocations and concrete type <-> interface conversions).
39      GopherLua API is **not** the stack based API.
40      GopherLua give preference to the user-friendliness over the performance.
41
42----------------------------------------------------------------
43How about performance?
44----------------------------------------------------------------
45GopherLua is not fast but not too slow, I think.
46
47GopherLua has almost equivalent ( or little bit better ) performance as Python3 on micro benchmarks.
48
49There are some benchmarks on the `wiki page <https://github.com/yuin/gopher-lua/wiki/Benchmarks>`_ .
50
51----------------------------------------------------------------
52Installation
53----------------------------------------------------------------
54
55.. code-block:: bash
56
57   go get github.com/yuin/gopher-lua
58
59GopherLua supports >= Go1.9.
60
61----------------------------------------------------------------
62Usage
63----------------------------------------------------------------
64GopherLua APIs perform in much the same way as Lua, **but the stack is used only
65for passing arguments and receiving returned values.**
66
67GopherLua supports channel operations. See **"Goroutines"** section.
68
69Import a package.
70
71.. code-block:: go
72
73   import (
74       "github.com/yuin/gopher-lua"
75   )
76
77Run scripts in the VM.
78
79.. code-block:: go
80
81   L := lua.NewState()
82   defer L.Close()
83   if err := L.DoString(`print("hello")`); err != nil {
84       panic(err)
85   }
86
87.. code-block:: go
88
89   L := lua.NewState()
90   defer L.Close()
91   if err := L.DoFile("hello.lua"); err != nil {
92       panic(err)
93   }
94
95Refer to `Lua Reference Manual <http://www.lua.org/manual/5.1/>`_ and `Go doc <http://godoc.org/github.com/yuin/gopher-lua>`_ for further information.
96
97Note that elements that are not commented in `Go doc <http://godoc.org/github.com/yuin/gopher-lua>`_ equivalent to `Lua Reference Manual <http://www.lua.org/manual/5.1/>`_ , except GopherLua uses objects instead of Lua stack indices.
98
99~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
100Data model
101~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
102All data in a GopherLua program is an ``LValue`` . ``LValue`` is an interface
103type that has following methods.
104
105- ``String() string``
106- ``Type() LValueType``
107
108
109Objects implement an LValue interface are
110
111================ ========================= ================== =======================
112 Type name        Go type                   Type() value       Constants
113================ ========================= ================== =======================
114 ``LNilType``      (constants)              ``LTNil``          ``LNil``
115 ``LBool``         (constants)              ``LTBool``         ``LTrue``, ``LFalse``
116 ``LNumber``        float64                 ``LTNumber``       ``-``
117 ``LString``        string                  ``LTString``       ``-``
118 ``LFunction``      struct pointer          ``LTFunction``     ``-``
119 ``LUserData``      struct pointer          ``LTUserData``     ``-``
120 ``LState``         struct pointer          ``LTThread``       ``-``
121 ``LTable``         struct pointer          ``LTTable``        ``-``
122 ``LChannel``       chan LValue             ``LTChannel``      ``-``
123================ ========================= ================== =======================
124
125You can test an object type in Go way(type assertion) or using a ``Type()`` value.
126
127.. code-block:: go
128
129   lv := L.Get(-1) // get the value at the top of the stack
130   if str, ok := lv.(lua.LString); ok {
131       // lv is LString
132       fmt.Println(string(str))
133   }
134   if lv.Type() != lua.LTString {
135       panic("string required.")
136   }
137
138.. code-block:: go
139
140   lv := L.Get(-1) // get the value at the top of the stack
141   if tbl, ok := lv.(*lua.LTable); ok {
142       // lv is LTable
143       fmt.Println(L.ObjLen(tbl))
144   }
145
146Note that ``LBool`` , ``LNumber`` , ``LString`` is not a pointer.
147
148To test ``LNilType`` and ``LBool``, You **must** use pre-defined constants.
149
150.. code-block:: go
151
152   lv := L.Get(-1) // get the value at the top of the stack
153
154   if lv == lua.LTrue { // correct
155   }
156
157   if bl, ok := lv.(lua.LBool); ok && bool(bl) { // wrong
158   }
159
160In Lua, both ``nil`` and ``false`` make a condition false. ``LVIsFalse`` and ``LVAsBool`` implement this specification.
161
162.. code-block:: go
163
164   lv := L.Get(-1) // get the value at the top of the stack
165   if lua.LVIsFalse(lv) { // lv is nil or false
166   }
167
168   if lua.LVAsBool(lv) { // lv is neither nil nor false
169   }
170
171Objects that based on go structs(``LFunction``. ``LUserData``, ``LTable``)
172have some public methods and fields. You can use these methods and fields for
173performance and debugging, but there are some limitations.
174
175- Metatable does not work.
176- No error handlings.
177
178~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
179Callstack & Registry size
180~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
181The size of an ``LState``'s callstack controls the maximum call depth for Lua functions within a script (Go function calls do not count).
182
183The registry of an ``LState`` implements stack storage for calling functions (both Lua and Go functions) and also for temporary variables in expressions. Its storage requirements will increase with callstack usage and also with code complexity.
184
185Both the registry and the callstack can be set to either a fixed size or to auto size.
186
187When you have a large number of ``LStates`` instantiated in a process, it's worth taking the time to tune the registry and callstack options.
188
189+++++++++
190Registry
191+++++++++
192
193The registry can have an initial size, a maximum size and a step size configured on a per ``LState`` basis. This will allow the registry to grow as needed. It will not shrink again after growing.
194
195.. code-block:: go
196
197    L := lua.NewState(lua.Options{
198       RegistrySize: 1024 * 20,         // this is the initial size of the registry
199       RegistryMaxSize: 1024 * 80,      // this is the maximum size that the registry can grow to. If set to `0` (the default) then the registry will not auto grow
200       RegistryGrowStep: 32,            // this is how much to step up the registry by each time it runs out of space. The default is `32`.
201    })
202   defer L.Close()
203
204A registry which is too small for a given script will ultimately result in a panic. A registry which is too big will waste memory (which can be significant if many ``LStates`` are instantiated).
205Auto growing registries incur a small performance hit at the point they are resized but will not otherwise affect performance.
206
207+++++++++
208Callstack
209+++++++++
210
211The callstack can operate in two different modes, fixed or auto size.
212A fixed size callstack has the highest performance and has a fixed memory overhead.
213An auto sizing callstack will allocate and release callstack pages on demand which will ensure the minimum amount of memory is in use at any time. The downside is it will incur a small performance impact every time a new page of callframes is allocated.
214By default an ``LState`` will allocate and free callstack frames in pages of 8, so the allocation overhead is not incurred on every function call. It is very likely that the performance impact of an auto resizing callstack will be negligible for most use cases.
215
216.. code-block:: go
217
218    L := lua.NewState(lua.Options{
219        CallStackSize: 120,                 // this is the maximum callstack size of this LState
220        MinimizeStackMemory: true,          // Defaults to `false` if not specified. If set, the callstack will auto grow and shrink as needed up to a max of `CallStackSize`. If not set, the callstack will be fixed at `CallStackSize`.
221    })
222   defer L.Close()
223
224++++++++++++++++
225Option defaults
226++++++++++++++++
227
228The above examples show how to customize the callstack and registry size on a per ``LState`` basis. You can also adjust some defaults for when options are not specified by altering the values of ``lua.RegistrySize``, ``lua.RegistryGrowStep`` and ``lua.CallStackSize``.
229
230An ``LState`` object that has been created by ``*LState#NewThread()`` inherits the callstack & registry size from the parent ``LState`` object.
231
232~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
233Miscellaneous lua.NewState options
234~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
235- **Options.SkipOpenLibs bool(default false)**
236    - By default, GopherLua opens all built-in libraries when new LState is created.
237    - You can skip this behaviour by setting this to ``true`` .
238    - Using the various `OpenXXX(L *LState) int` functions you can open only those libraries that you require, for an example see below.
239- **Options.IncludeGoStackTrace bool(default false)**
240    - By default, GopherLua does not show Go stack traces when panics occur.
241    - You can get Go stack traces by setting this to ``true`` .
242
243~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
244API
245~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
246
247Refer to `Lua Reference Manual <http://www.lua.org/manual/5.1/>`_ and `Go doc(LState methods) <http://godoc.org/github.com/yuin/gopher-lua>`_ for further information.
248
249+++++++++++++++++++++++++++++++++++++++++
250Calling Go from Lua
251+++++++++++++++++++++++++++++++++++++++++
252
253.. code-block:: go
254
255   func Double(L *lua.LState) int {
256       lv := L.ToInt(1)             /* get argument */
257       L.Push(lua.LNumber(lv * 2)) /* push result */
258       return 1                     /* number of results */
259   }
260
261   func main() {
262       L := lua.NewState()
263       defer L.Close()
264       L.SetGlobal("double", L.NewFunction(Double)) /* Original lua_setglobal uses stack... */
265   }
266
267.. code-block:: lua
268
269   print(double(20)) -- > "40"
270
271Any function registered with GopherLua is a ``lua.LGFunction``, defined in ``value.go``
272
273.. code-block:: go
274
275   type LGFunction func(*LState) int
276
277Working with coroutines.
278
279.. code-block:: go
280
281   co, _ := L.NewThread() /* create a new thread */
282   fn := L.GetGlobal("coro").(*lua.LFunction) /* get function from lua */
283   for {
284       st, err, values := L.Resume(co, fn)
285       if st == lua.ResumeError {
286           fmt.Println("yield break(error)")
287           fmt.Println(err.Error())
288           break
289       }
290
291       for i, lv := range values {
292           fmt.Printf("%v : %v\n", i, lv)
293       }
294
295       if st == lua.ResumeOK {
296           fmt.Println("yield break(ok)")
297           break
298       }
299   }
300
301+++++++++++++++++++++++++++++++++++++++++
302Opening a subset of builtin modules
303+++++++++++++++++++++++++++++++++++++++++
304
305The following demonstrates how to open a subset of the built-in modules in Lua, say for example to avoid enabling modules with access to local files or system calls.
306
307main.go
308
309.. code-block:: go
310
311    func main() {
312        L := lua.NewState(lua.Options{SkipOpenLibs: true})
313        defer L.Close()
314        for _, pair := range []struct {
315            n string
316            f lua.LGFunction
317        }{
318            {lua.LoadLibName, lua.OpenPackage}, // Must be first
319            {lua.BaseLibName, lua.OpenBase},
320            {lua.TabLibName, lua.OpenTable},
321        } {
322            if err := L.CallByParam(lua.P{
323                Fn:      L.NewFunction(pair.f),
324                NRet:    0,
325                Protect: true,
326            }, lua.LString(pair.n)); err != nil {
327                panic(err)
328            }
329        }
330        if err := L.DoFile("main.lua"); err != nil {
331            panic(err)
332        }
333    }
334
335+++++++++++++++++++++++++++++++++++++++++
336Creating a module by Go
337+++++++++++++++++++++++++++++++++++++++++
338
339mymodule.go
340
341.. code-block:: go
342
343    package mymodule
344
345    import (
346        "github.com/yuin/gopher-lua"
347    )
348
349    func Loader(L *lua.LState) int {
350        // register functions to the table
351        mod := L.SetFuncs(L.NewTable(), exports)
352        // register other stuff
353        L.SetField(mod, "name", lua.LString("value"))
354
355        // returns the module
356        L.Push(mod)
357        return 1
358    }
359
360    var exports = map[string]lua.LGFunction{
361        "myfunc": myfunc,
362    }
363
364    func myfunc(L *lua.LState) int {
365        return 0
366    }
367
368mymain.go
369
370.. code-block:: go
371
372    package main
373
374    import (
375        "./mymodule"
376        "github.com/yuin/gopher-lua"
377    )
378
379    func main() {
380        L := lua.NewState()
381        defer L.Close()
382        L.PreloadModule("mymodule", mymodule.Loader)
383        if err := L.DoFile("main.lua"); err != nil {
384            panic(err)
385        }
386    }
387
388main.lua
389
390.. code-block:: lua
391
392    local m = require("mymodule")
393    m.myfunc()
394    print(m.name)
395
396
397+++++++++++++++++++++++++++++++++++++++++
398Calling Lua from Go
399+++++++++++++++++++++++++++++++++++++++++
400
401.. code-block:: go
402
403   L := lua.NewState()
404   defer L.Close()
405   if err := L.DoFile("double.lua"); err != nil {
406       panic(err)
407   }
408   if err := L.CallByParam(lua.P{
409       Fn: L.GetGlobal("double"),
410       NRet: 1,
411       Protect: true,
412       }, lua.LNumber(10)); err != nil {
413       panic(err)
414   }
415   ret := L.Get(-1) // returned value
416   L.Pop(1)  // remove received value
417
418If ``Protect`` is false, GopherLua will panic instead of returning an ``error`` value.
419
420+++++++++++++++++++++++++++++++++++++++++
421User-Defined types
422+++++++++++++++++++++++++++++++++++++++++
423You can extend GopherLua with new types written in Go.
424``LUserData`` is provided for this purpose.
425
426.. code-block:: go
427
428    type Person struct {
429        Name string
430    }
431
432    const luaPersonTypeName = "person"
433
434    // Registers my person type to given L.
435    func registerPersonType(L *lua.LState) {
436        mt := L.NewTypeMetatable(luaPersonTypeName)
437        L.SetGlobal("person", mt)
438        // static attributes
439        L.SetField(mt, "new", L.NewFunction(newPerson))
440        // methods
441        L.SetField(mt, "__index", L.SetFuncs(L.NewTable(), personMethods))
442    }
443
444    // Constructor
445    func newPerson(L *lua.LState) int {
446        person := &Person{L.CheckString(1)}
447        ud := L.NewUserData()
448        ud.Value = person
449        L.SetMetatable(ud, L.GetTypeMetatable(luaPersonTypeName))
450        L.Push(ud)
451        return 1
452    }
453
454    // Checks whether the first lua argument is a *LUserData with *Person and returns this *Person.
455    func checkPerson(L *lua.LState) *Person {
456        ud := L.CheckUserData(1)
457        if v, ok := ud.Value.(*Person); ok {
458            return v
459        }
460        L.ArgError(1, "person expected")
461        return nil
462    }
463
464    var personMethods = map[string]lua.LGFunction{
465        "name": personGetSetName,
466    }
467
468    // Getter and setter for the Person#Name
469    func personGetSetName(L *lua.LState) int {
470        p := checkPerson(L)
471        if L.GetTop() == 2 {
472            p.Name = L.CheckString(2)
473            return 0
474        }
475        L.Push(lua.LString(p.Name))
476        return 1
477    }
478
479    func main() {
480        L := lua.NewState()
481        defer L.Close()
482        registerPersonType(L)
483        if err := L.DoString(`
484            p = person.new("Steeve")
485            print(p:name()) -- "Steeve"
486            p:name("Alice")
487            print(p:name()) -- "Alice"
488        `); err != nil {
489            panic(err)
490        }
491    }
492
493+++++++++++++++++++++++++++++++++++++++++
494Terminating a running LState
495+++++++++++++++++++++++++++++++++++++++++
496GopherLua supports the `Go Concurrency Patterns: Context <https://blog.golang.org/context>`_ .
497
498
499.. code-block:: go
500
501    L := lua.NewState()
502    defer L.Close()
503    ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
504    defer cancel()
505    // set the context to our LState
506    L.SetContext(ctx)
507    err := L.DoString(`
508      local clock = os.clock
509      function sleep(n)  -- seconds
510        local t0 = clock()
511        while clock() - t0 <= n do end
512      end
513      sleep(3)
514    `)
515    // err.Error() contains "context deadline exceeded"
516
517With coroutines
518
519.. code-block:: go
520
521	L := lua.NewState()
522	defer L.Close()
523	ctx, cancel := context.WithCancel(context.Background())
524	L.SetContext(ctx)
525	defer cancel()
526	L.DoString(`
527	    function coro()
528		  local i = 0
529		  while true do
530		    coroutine.yield(i)
531			i = i+1
532		  end
533		  return i
534	    end
535	`)
536	co, cocancel := L.NewThread()
537	defer cocancel()
538	fn := L.GetGlobal("coro").(*LFunction)
539
540	_, err, values := L.Resume(co, fn) // err is nil
541
542	cancel() // cancel the parent context
543
544	_, err, values = L.Resume(co, fn) // err is NOT nil : child context was canceled
545
546**Note that using a context causes performance degradation.**
547
548.. code-block::
549
550    time ./glua-with-context.exe fib.lua
551    9227465
552    0.01s user 0.11s system 1% cpu 7.505 total
553
554    time ./glua-without-context.exe fib.lua
555    9227465
556    0.01s user 0.01s system 0% cpu 5.306 total
557
558+++++++++++++++++++++++++++++++++++++++++
559Sharing Lua byte code between LStates
560+++++++++++++++++++++++++++++++++++++++++
561Calling ``DoFile`` will load a Lua script, compile it to byte code and run the byte code in a ``LState``.
562
563If you have multiple ``LStates`` which are all required to run the same script, you can share the byte code between them,
564which will save on memory.
565Sharing byte code is safe as it is read only and cannot be altered by lua scripts.
566
567.. code-block:: go
568
569    // CompileLua reads the passed lua file from disk and compiles it.
570    func CompileLua(filePath string) (*lua.FunctionProto, error) {
571        file, err := os.Open(filePath)
572        defer file.Close()
573        if err != nil {
574            return nil, err
575        }
576        reader := bufio.NewReader(file)
577        chunk, err := parse.Parse(reader, filePath)
578        if err != nil {
579            return nil, err
580        }
581        proto, err := lua.Compile(chunk, filePath)
582        if err != nil {
583            return nil, err
584        }
585        return proto, nil
586    }
587
588    // DoCompiledFile takes a FunctionProto, as returned by CompileLua, and runs it in the LState. It is equivalent
589    // to calling DoFile on the LState with the original source file.
590    func DoCompiledFile(L *lua.LState, proto *lua.FunctionProto) error {
591        lfunc := L.NewFunctionFromProto(proto)
592        L.Push(lfunc)
593        return L.PCall(0, lua.MultRet, nil)
594    }
595
596    // Example shows how to share the compiled byte code from a lua script between multiple VMs.
597    func Example() {
598        codeToShare := CompileLua("mylua.lua")
599        a := lua.NewState()
600        b := lua.NewState()
601        c := lua.NewState()
602        DoCompiledFile(a, codeToShare)
603        DoCompiledFile(b, codeToShare)
604        DoCompiledFile(c, codeToShare)
605    }
606
607+++++++++++++++++++++++++++++++++++++++++
608Goroutines
609+++++++++++++++++++++++++++++++++++++++++
610The ``LState`` is not goroutine-safe. It is recommended to use one LState per goroutine and communicate between goroutines by using channels.
611
612Channels are represented by ``channel`` objects in GopherLua. And a ``channel`` table provides functions for performing channel operations.
613
614Some objects can not be sent over channels due to having non-goroutine-safe objects inside itself.
615
616- a thread(state)
617- a function
618- an userdata
619- a table with a metatable
620
621You **must not** send these objects from Go APIs to channels.
622
623
624
625.. code-block:: go
626
627    func receiver(ch, quit chan lua.LValue) {
628        L := lua.NewState()
629        defer L.Close()
630        L.SetGlobal("ch", lua.LChannel(ch))
631        L.SetGlobal("quit", lua.LChannel(quit))
632        if err := L.DoString(`
633        local exit = false
634        while not exit do
635          channel.select(
636            {"|<-", ch, function(ok, v)
637              if not ok then
638                print("channel closed")
639                exit = true
640              else
641                print("received:", v)
642              end
643            end},
644            {"|<-", quit, function(ok, v)
645                print("quit")
646                exit = true
647            end}
648          )
649        end
650      `); err != nil {
651            panic(err)
652        }
653    }
654
655    func sender(ch, quit chan lua.LValue) {
656        L := lua.NewState()
657        defer L.Close()
658        L.SetGlobal("ch", lua.LChannel(ch))
659        L.SetGlobal("quit", lua.LChannel(quit))
660        if err := L.DoString(`
661        ch:send("1")
662        ch:send("2")
663      `); err != nil {
664            panic(err)
665        }
666        ch <- lua.LString("3")
667        quit <- lua.LTrue
668    }
669
670    func main() {
671        ch := make(chan lua.LValue)
672        quit := make(chan lua.LValue)
673        go receiver(ch, quit)
674        go sender(ch, quit)
675        time.Sleep(3 * time.Second)
676    }
677
678'''''''''''''''
679Go API
680'''''''''''''''
681
682``ToChannel``, ``CheckChannel``, ``OptChannel`` are available.
683
684Refer to `Go doc(LState methods) <http://godoc.org/github.com/yuin/gopher-lua>`_ for further information.
685
686'''''''''''''''
687Lua API
688'''''''''''''''
689
690- **channel.make([buf:int]) -> ch:channel**
691    - Create new channel that has a buffer size of ``buf``. By default, ``buf`` is 0.
692
693- **channel.select(case:table [, case:table, case:table ...]) -> {index:int, recv:any, ok}**
694    - Same as the ``select`` statement in Go. It returns the index of the chosen case and, if that
695      case was a receive operation, the value received and a boolean indicating whether the channel has been closed.
696    - ``case`` is a table that outlined below.
697        - receiving: `{"|<-", ch:channel [, handler:func(ok, data:any)]}`
698        - sending: `{"<-|", ch:channel, data:any [, handler:func(data:any)]}`
699        - default: `{"default" [, handler:func()]}`
700
701``channel.select`` examples:
702
703.. code-block:: lua
704
705    local idx, recv, ok = channel.select(
706      {"|<-", ch1},
707      {"|<-", ch2}
708    )
709    if not ok then
710        print("closed")
711    elseif idx == 1 then -- received from ch1
712        print(recv)
713    elseif idx == 2 then -- received from ch2
714        print(recv)
715    end
716
717.. code-block:: lua
718
719    channel.select(
720      {"|<-", ch1, function(ok, data)
721        print(ok, data)
722      end},
723      {"<-|", ch2, "value", function(data)
724        print(data)
725      end},
726      {"default", function()
727        print("default action")
728      end}
729    )
730
731- **channel:send(data:any)**
732    - Send ``data`` over the channel.
733- **channel:receive() -> ok:bool, data:any**
734    - Receive some data over the channel.
735- **channel:close()**
736    - Close the channel.
737
738''''''''''''''''''''''''''''''
739The LState pool pattern
740''''''''''''''''''''''''''''''
741To create per-thread LState instances, You can use the ``sync.Pool`` like mechanism.
742
743.. code-block:: go
744
745    type lStatePool struct {
746        m     sync.Mutex
747        saved []*lua.LState
748    }
749
750    func (pl *lStatePool) Get() *lua.LState {
751        pl.m.Lock()
752        defer pl.m.Unlock()
753        n := len(pl.saved)
754        if n == 0 {
755            return pl.New()
756        }
757        x := pl.saved[n-1]
758        pl.saved = pl.saved[0 : n-1]
759        return x
760    }
761
762    func (pl *lStatePool) New() *lua.LState {
763        L := lua.NewState()
764        // setting the L up here.
765        // load scripts, set global variables, share channels, etc...
766        return L
767    }
768
769    func (pl *lStatePool) Put(L *lua.LState) {
770        pl.m.Lock()
771        defer pl.m.Unlock()
772        pl.saved = append(pl.saved, L)
773    }
774
775    func (pl *lStatePool) Shutdown() {
776        for _, L := range pl.saved {
777            L.Close()
778        }
779    }
780
781    // Global LState pool
782    var luaPool = &lStatePool{
783        saved: make([]*lua.LState, 0, 4),
784    }
785
786Now, you can get per-thread LState objects from the ``luaPool`` .
787
788.. code-block:: go
789
790    func MyWorker() {
791       L := luaPool.Get()
792       defer luaPool.Put(L)
793       /* your code here */
794    }
795
796    func main() {
797        defer luaPool.Shutdown()
798        go MyWorker()
799        go MyWorker()
800        /* etc... */
801    }
802
803
804----------------------------------------------------------------
805Differences between Lua and GopherLua
806----------------------------------------------------------------
807~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
808Goroutines
809~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
810
811- GopherLua supports channel operations.
812    - GopherLua has a type named ``channel``.
813    - The ``channel`` table provides functions for performing channel operations.
814
815~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
816Unsupported functions
817~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
818
819- ``string.dump``
820- ``os.setlocale``
821- ``lua_Debug.namewhat``
822- ``package.loadlib``
823- debug hooks
824
825~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
826Miscellaneous notes
827~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
828
829- ``collectgarbage`` does not take any arguments and runs the garbage collector for the entire Go program.
830- ``file:setvbuf`` does not support a line buffering.
831- Daylight saving time is not supported.
832- GopherLua has a function to set an environment variable : ``os.setenv(name, value)``
833
834----------------------------------------------------------------
835Standalone interpreter
836----------------------------------------------------------------
837Lua has an interpreter called ``lua`` . GopherLua has an interpreter called ``glua`` .
838
839.. code-block:: bash
840
841   go get github.com/yuin/gopher-lua/cmd/glua
842
843``glua`` has same options as ``lua`` .
844
845----------------------------------------------------------------
846How to Contribute
847----------------------------------------------------------------
848See `Guidlines for contributors <https://github.com/yuin/gopher-lua/tree/master/.github/CONTRIBUTING.md>`_ .
849
850----------------------------------------------------------------
851Libraries for GopherLua
852----------------------------------------------------------------
853
854- `gopher-luar <https://github.com/layeh/gopher-luar>`_ : Simplifies data passing to and from gopher-lua
855- `gluamapper <https://github.com/yuin/gluamapper>`_ : Mapping a Lua table to a Go struct
856- `gluare <https://github.com/yuin/gluare>`_ : Regular expressions for gopher-lua
857- `gluahttp <https://github.com/cjoudrey/gluahttp>`_ : HTTP request module for gopher-lua
858- `gopher-json <https://github.com/layeh/gopher-json>`_ : A simple JSON encoder/decoder for gopher-lua
859- `gluayaml <https://github.com/kohkimakimoto/gluayaml>`_ : Yaml parser for gopher-lua
860- `glua-lfs <https://github.com/layeh/gopher-lfs>`_ : Partially implements the luafilesystem module for gopher-lua
861- `gluaurl <https://github.com/cjoudrey/gluaurl>`_ : A url parser/builder module for gopher-lua
862- `gluahttpscrape <https://github.com/felipejfc/gluahttpscrape>`_ : A simple HTML scraper module for gopher-lua
863- `gluaxmlpath <https://github.com/ailncode/gluaxmlpath>`_ : An xmlpath module for gopher-lua
864- `gmoonscript <https://github.com/rucuriousyet/gmoonscript>`_ : Moonscript Compiler for the Gopher Lua VM
865- `loguago <https://github.com/rucuriousyet/loguago>`_ : Zerolog wrapper for Gopher-Lua
866- `gluacrypto <https://github.com/tengattack/gluacrypto>`_ : A native Go implementation of crypto library for the GopherLua VM.
867- `gluasql <https://github.com/tengattack/gluasql>`_ : A native Go implementation of SQL client for the GopherLua VM.
868- `purr <https://github.com/leyafo/purr>`_ : A http mock testing tool.
869- `vadv/gopher-lua-libs <https://github.com/vadv/gopher-lua-libs>`_ : Some usefull libraries for GopherLua VM.
870- `gluaperiphery <https://github.com/BixData/gluaperiphery>`_ : A periphery library for the GopherLua VM (GPIO, SPI, I2C, MMIO, and Serial peripheral I/O for Linux).
871- `glua-async <https://github.com/CuberL/glua-async>`_ : An async/await implement for gopher-lua.
872- `gopherlua-debugger <https://github.com/edolphin-ydf/gopherlua-debugger>`_ : A debugger for gopher-lua
873----------------------------------------------------------------
874Donation
875----------------------------------------------------------------
876
877BTC: 1NEDSyUmo4SMTDP83JJQSWi1MvQUGGNMZB
878
879----------------------------------------------------------------
880License
881----------------------------------------------------------------
882MIT
883
884----------------------------------------------------------------
885Author
886----------------------------------------------------------------
887Yusuke Inuzuka
888