github.com/yuin/gopher-lua@v1.1.2-0.20231212122839-2348fd042596/README.rst (about)

     1  
     2  ===============================================================================
     3  GopherLua: VM and compiler for Lua in Go.
     4  ===============================================================================
     5  
     6  .. image:: https://pkg.go.dev/badge/github.com/yuin/gopher-lua.svg
     7      :target: https://pkg.go.dev/github.com/yuin/gopher-lua
     8  
     9  .. image:: https://github.com/yuin/gopher-lua/workflows/test/badge.svg?branch=master&event=push
    10      :target: https://github.com/yuin/gopher-lua/actions?query=workflow:test
    11  
    12  .. image:: https://coveralls.io/repos/github/yuin/gopher-lua/badge.svg?branch=master
    13      :target: https://coveralls.io/github/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  
    22  GopherLua is a Lua5.1(+ `goto` statement in Lua5.2) VM and compiler written in Go. GopherLua has a same goal
    23  with Lua: **Be a scripting language with extensible semantics** . It provides
    24  Go APIs that allow you to easily embed a scripting language to your Go host
    25  programs.
    26  
    27  .. contents::
    28     :depth: 1
    29  
    30  ----------------------------------------------------------------
    31  Design 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  ----------------------------------------------------------------
    43  How about performance?
    44  ----------------------------------------------------------------
    45  GopherLua is not fast but not too slow, I think.
    46  
    47  GopherLua has almost equivalent ( or little bit better ) performance as Python3 on micro benchmarks.
    48  
    49  There are some benchmarks on the `wiki page <https://github.com/yuin/gopher-lua/wiki/Benchmarks>`_ .
    50  
    51  ----------------------------------------------------------------
    52  Installation
    53  ----------------------------------------------------------------
    54  
    55  .. code-block:: bash
    56  
    57     go get github.com/yuin/gopher-lua
    58  
    59  GopherLua supports >= Go1.9.
    60  
    61  ----------------------------------------------------------------
    62  Usage
    63  ----------------------------------------------------------------
    64  GopherLua APIs perform in much the same way as Lua, **but the stack is used only
    65  for passing arguments and receiving returned values.**
    66  
    67  GopherLua supports channel operations. See **"Goroutines"** section.
    68  
    69  Import a package.
    70  
    71  .. code-block:: go
    72  
    73     import (
    74         "github.com/yuin/gopher-lua"
    75     )
    76  
    77  Run 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  
    95  Refer 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  
    97  Note 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  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   100  Data model
   101  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   102  All data in a GopherLua program is an ``LValue`` . ``LValue`` is an interface
   103  type that has following methods.
   104  
   105  - ``String() string``
   106  - ``Type() LValueType``
   107  
   108  
   109  Objects 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  
   125  You 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  
   146  Note that ``LBool`` , ``LNumber`` , ``LString`` is not a pointer.
   147  
   148  To 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  
   160  In 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  
   171  Objects that based on go structs(``LFunction``. ``LUserData``, ``LTable``)
   172  have some public methods and fields. You can use these methods and fields for
   173  performance and debugging, but there are some limitations.
   174  
   175  - Metatable does not work.
   176  - No error handlings.
   177  
   178  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   179  Callstack & Registry size
   180  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   181  The size of an ``LState``'s callstack controls the maximum call depth for Lua functions within a script (Go function calls do not count).
   182  
   183  The 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  
   185  Both the registry and the callstack can be set to either a fixed size or to auto size.
   186  
   187  When 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  +++++++++
   190  Registry
   191  +++++++++
   192  
   193  The 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  
   204  A 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).
   205  Auto growing registries incur a small performance hit at the point they are resized but will not otherwise affect performance.
   206  
   207  +++++++++
   208  Callstack
   209  +++++++++
   210  
   211  The callstack can operate in two different modes, fixed or auto size.
   212  A fixed size callstack has the highest performance and has a fixed memory overhead.
   213  An 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.
   214  By 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  ++++++++++++++++
   225  Option defaults
   226  ++++++++++++++++
   227  
   228  The 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  
   230  An ``LState`` object that has been created by ``*LState#NewThread()`` inherits the callstack & registry size from the parent ``LState`` object.
   231  
   232  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   233  Miscellaneous 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  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   244  API
   245  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   246  
   247  Refer 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  +++++++++++++++++++++++++++++++++++++++++
   250  Calling 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  
   271  Any 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  
   277  Working 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  +++++++++++++++++++++++++++++++++++++++++
   302  Opening a subset of builtin modules
   303  +++++++++++++++++++++++++++++++++++++++++
   304  
   305  The 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  
   307  main.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  +++++++++++++++++++++++++++++++++++++++++
   336  Creating a module by Go
   337  +++++++++++++++++++++++++++++++++++++++++
   338  
   339  mymodule.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  
   368  mymain.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  
   388  main.lua
   389  
   390  .. code-block:: lua
   391  
   392      local m = require("mymodule")
   393      m.myfunc()
   394      print(m.name)
   395  
   396  
   397  +++++++++++++++++++++++++++++++++++++++++
   398  Calling 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  
   418  If ``Protect`` is false, GopherLua will panic instead of returning an ``error`` value.
   419  
   420  +++++++++++++++++++++++++++++++++++++++++
   421  User-Defined types
   422  +++++++++++++++++++++++++++++++++++++++++
   423  You 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  +++++++++++++++++++++++++++++++++++++++++
   494  Terminating a running LState
   495  +++++++++++++++++++++++++++++++++++++++++
   496  GopherLua 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  
   517  With 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  +++++++++++++++++++++++++++++++++++++++++
   559  Sharing Lua byte code between LStates
   560  +++++++++++++++++++++++++++++++++++++++++
   561  Calling ``DoFile`` will load a Lua script, compile it to byte code and run the byte code in a ``LState``.
   562  
   563  If you have multiple ``LStates`` which are all required to run the same script, you can share the byte code between them,
   564  which will save on memory.
   565  Sharing 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  +++++++++++++++++++++++++++++++++++++++++
   608  Goroutines
   609  +++++++++++++++++++++++++++++++++++++++++
   610  The ``LState`` is not goroutine-safe. It is recommended to use one LState per goroutine and communicate between goroutines by using channels.
   611  
   612  Channels are represented by ``channel`` objects in GopherLua. And a ``channel`` table provides functions for performing channel operations.
   613  
   614  Some 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  
   621  You **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  '''''''''''''''
   679  Go API
   680  '''''''''''''''
   681  
   682  ``ToChannel``, ``CheckChannel``, ``OptChannel`` are available.
   683  
   684  Refer to `Go doc(LState methods) <http://godoc.org/github.com/yuin/gopher-lua>`_ for further information.
   685  
   686  '''''''''''''''
   687  Lua 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  ''''''''''''''''''''''''''''''
   739  The LState pool pattern
   740  ''''''''''''''''''''''''''''''
   741  To 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  
   786  Now, 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  ----------------------------------------------------------------
   805  Differences between Lua and GopherLua
   806  ----------------------------------------------------------------
   807  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   808  Goroutines
   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  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   816  Unsupported functions
   817  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   818  
   819  - ``string.dump``
   820  - ``os.setlocale``
   821  - ``lua_Debug.namewhat``
   822  - ``package.loadlib``
   823  - debug hooks
   824  
   825  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   826  Miscellaneous 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  - GopherLua support ``goto`` and ``::label::`` statement in Lua5.2.
   834      - `goto` is a keyword and not a valid variable name.
   835  
   836  ----------------------------------------------------------------
   837  Standalone interpreter
   838  ----------------------------------------------------------------
   839  Lua has an interpreter called ``lua`` . GopherLua has an interpreter called ``glua`` .
   840  
   841  .. code-block:: bash
   842  
   843     go get github.com/yuin/gopher-lua/cmd/glua
   844  
   845  ``glua`` has same options as ``lua`` .
   846  
   847  ----------------------------------------------------------------
   848  How to Contribute
   849  ----------------------------------------------------------------
   850  See `Guidlines for contributors <https://github.com/yuin/gopher-lua/tree/master/.github/CONTRIBUTING.md>`_ .
   851  
   852  ----------------------------------------------------------------
   853  Libraries for GopherLua
   854  ----------------------------------------------------------------
   855  
   856  - `gopher-luar <https://github.com/layeh/gopher-luar>`_ : Simplifies data passing to and from gopher-lua
   857  - `gluamapper <https://github.com/yuin/gluamapper>`_ : Mapping a Lua table to a Go struct
   858  - `gluare <https://github.com/yuin/gluare>`_ : Regular expressions for gopher-lua
   859  - `gluahttp <https://github.com/cjoudrey/gluahttp>`_ : HTTP request module for gopher-lua
   860  - `gopher-json <https://github.com/layeh/gopher-json>`_ : A simple JSON encoder/decoder for gopher-lua
   861  - `gluayaml <https://github.com/kohkimakimoto/gluayaml>`_ : Yaml parser for gopher-lua
   862  - `glua-lfs <https://github.com/layeh/gopher-lfs>`_ : Partially implements the luafilesystem module for gopher-lua
   863  - `gluaurl <https://github.com/cjoudrey/gluaurl>`_ : A url parser/builder module for gopher-lua
   864  - `gluahttpscrape <https://github.com/felipejfc/gluahttpscrape>`_ : A simple HTML scraper module for gopher-lua
   865  - `gluaxmlpath <https://github.com/ailncode/gluaxmlpath>`_ : An xmlpath module for gopher-lua
   866  - `gmoonscript <https://github.com/rucuriousyet/gmoonscript>`_ : Moonscript Compiler for the Gopher Lua VM
   867  - `loguago <https://github.com/rucuriousyet/loguago>`_ : Zerolog wrapper for Gopher-Lua
   868  - `gluacrypto <https://github.com/tengattack/gluacrypto>`_ : A native Go implementation of crypto library for the GopherLua VM.
   869  - `gluasql <https://github.com/tengattack/gluasql>`_ : A native Go implementation of SQL client for the GopherLua VM.
   870  - `purr <https://github.com/leyafo/purr>`_ : A http mock testing tool.
   871  - `vadv/gopher-lua-libs <https://github.com/vadv/gopher-lua-libs>`_ : Some usefull libraries for GopherLua VM.
   872  - `gluasocket <https://gitlab.com/megalithic-llc/gluasocket>`_ : A native Go implementation of LuaSocket for the GopherLua VM.
   873  - `glua-async <https://github.com/CuberL/glua-async>`_ : An async/await implement for gopher-lua.
   874  - `gopherlua-debugger <https://github.com/edolphin-ydf/gopherlua-debugger>`_ : A debugger for gopher-lua
   875  - `gluamahonia <https://github.com/super1207/gluamahonia>`_ : An encoding converter for gopher-lua
   876  ----------------------------------------------------------------
   877  Donation
   878  ----------------------------------------------------------------
   879  
   880  BTC: 1NEDSyUmo4SMTDP83JJQSWi1MvQUGGNMZB
   881  
   882  ----------------------------------------------------------------
   883  License
   884  ----------------------------------------------------------------
   885  MIT
   886  
   887  ----------------------------------------------------------------
   888  Author
   889  ----------------------------------------------------------------
   890  Yusuke Inuzuka