github.com/bitxmesh/gopher-lua@v0.0.0-20190327085718-93c344ef97a4/README.rst (about)

     1  
     2  ===============================================================================
     3  GopherLua: 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  
    22  GopherLua is a Lua5.1 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  Size of the callstack & registry is **fixed** for mainly performance.
   182  You can change the default size of the callstack & registry.
   183  
   184  .. code-block:: go
   185  
   186     lua.RegistrySize = 1024 * 20
   187     lua.CallStackSize = 1024
   188     L := lua.NewState()
   189     defer L.Close()
   190  
   191  You can also create an LState object that has the callstack & registry size specified by ``Options`` .
   192  
   193  .. code-block:: go
   194  
   195      L := lua.NewState(lua.Options{
   196          CallStackSize: 120,
   197          RegistrySize:  120*20,
   198      })
   199  
   200  An LState object that has been created by ``*LState#NewThread()`` inherits the callstack & registry size from the parent LState object.
   201  
   202  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   203  Miscellaneous lua.NewState options
   204  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   205  - **Options.SkipOpenLibs bool(default false)**
   206      - By default, GopherLua opens all built-in libraries when new LState is created.
   207      - You can skip this behaviour by setting this to ``true`` .
   208      - Using the various `OpenXXX(L *LState) int` functions you can open only those libraries that you require, for an example see below.
   209  - **Options.IncludeGoStackTrace bool(default false)**
   210      - By default, GopherLua does not show Go stack traces when panics occur.
   211      - You can get Go stack traces by setting this to ``true`` .
   212  
   213  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   214  API
   215  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   216  
   217  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.
   218  
   219  +++++++++++++++++++++++++++++++++++++++++
   220  Calling Go from Lua
   221  +++++++++++++++++++++++++++++++++++++++++
   222  
   223  .. code-block:: go
   224  
   225     func Double(L *lua.LState) int {
   226         lv := L.ToInt(1)             /* get argument */
   227         L.Push(lua.LNumber(lv * 2)) /* push result */
   228         return 1                     /* number of results */
   229     }
   230  
   231     func main() {
   232         L := lua.NewState()
   233         defer L.Close()
   234         L.SetGlobal("double", L.NewFunction(Double)) /* Original lua_setglobal uses stack... */
   235     }
   236  
   237  .. code-block:: lua
   238  
   239     print(double(20)) -- > "40"
   240  
   241  Any function registered with GopherLua is a ``lua.LGFunction``, defined in ``value.go``
   242  
   243  .. code-block:: go
   244  
   245     type LGFunction func(*LState) int
   246  
   247  Working with coroutines.
   248  
   249  .. code-block:: go
   250  
   251     co, _ := L.NewThread() /* create a new thread */
   252     fn := L.GetGlobal("coro").(*lua.LFunction) /* get function from lua */
   253     for {
   254         st, err, values := L.Resume(co, fn)
   255         if st == lua.ResumeError {
   256             fmt.Println("yield break(error)")
   257             fmt.Println(err.Error())
   258             break
   259         }
   260  
   261         for i, lv := range values {
   262             fmt.Printf("%v : %v\n", i, lv)
   263         }
   264  
   265         if st == lua.ResumeOK {
   266             fmt.Println("yield break(ok)")
   267             break
   268         }
   269     }
   270  
   271  +++++++++++++++++++++++++++++++++++++++++
   272  Opening a subset of builtin modules
   273  +++++++++++++++++++++++++++++++++++++++++
   274  
   275  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.
   276  
   277  main.go
   278  
   279  .. code-block:: go
   280  
   281      func main() {
   282          L := lua.NewState(lua.Options{SkipOpenLibs: true})
   283          defer L.Close()
   284          for _, pair := range []struct {
   285              n string
   286              f lua.LGFunction
   287          }{
   288              {lua.LoadLibName, lua.OpenPackage}, // Must be first
   289              {lua.BaseLibName, lua.OpenBase},
   290              {lua.TabLibName, lua.OpenTable},
   291          } {
   292              if err := L.CallByParam(lua.P{
   293                  Fn:      L.NewFunction(pair.f),
   294                  NRet:    0,
   295                  Protect: true,
   296              }, lua.LString(pair.n)); err != nil {
   297                  panic(err)
   298              }
   299          }
   300          if err := L.DoFile("main.lua"); err != nil {
   301              panic(err)
   302          }
   303      }
   304  
   305  +++++++++++++++++++++++++++++++++++++++++
   306  Creating a module by Go
   307  +++++++++++++++++++++++++++++++++++++++++
   308  
   309  mymodule.go
   310  
   311  .. code-block:: go
   312  
   313      package mymodule
   314  
   315      import (
   316          "github.com/yuin/gopher-lua"
   317      )
   318  
   319      func Loader(L *lua.LState) int {
   320          // register functions to the table
   321          mod := L.SetFuncs(L.NewTable(), exports)
   322          // register other stuff
   323          L.SetField(mod, "name", lua.LString("value"))
   324  
   325          // returns the module
   326          L.Push(mod)
   327          return 1
   328      }
   329  
   330      var exports = map[string]lua.LGFunction{
   331          "myfunc": myfunc,
   332      }
   333  
   334      func myfunc(L *lua.LState) int {
   335          return 0
   336      }
   337  
   338  mymain.go
   339  
   340  .. code-block:: go
   341  
   342      package main
   343  
   344      import (
   345          "./mymodule"
   346          "github.com/yuin/gopher-lua"
   347      )
   348  
   349      func main() {
   350          L := lua.NewState()
   351          defer L.Close()
   352          L.PreloadModule("mymodule", mymodule.Loader)
   353          if err := L.DoFile("main.lua"); err != nil {
   354              panic(err)
   355          }
   356      }
   357  
   358  main.lua
   359  
   360  .. code-block:: lua
   361  
   362      local m = require("mymodule")
   363      m.myfunc()
   364      print(m.name)
   365  
   366  
   367  +++++++++++++++++++++++++++++++++++++++++
   368  Calling Lua from Go
   369  +++++++++++++++++++++++++++++++++++++++++
   370  
   371  .. code-block:: go
   372  
   373     L := lua.NewState()
   374     defer L.Close()
   375     if err := L.DoFile("double.lua"); err != nil {
   376         panic(err)
   377     }
   378     if err := L.CallByParam(lua.P{
   379         Fn: L.GetGlobal("double"),
   380         NRet: 1,
   381         Protect: true,
   382         }, lua.LNumber(10)); err != nil {
   383         panic(err)
   384     }
   385     ret := L.Get(-1) // returned value
   386     L.Pop(1)  // remove received value
   387  
   388  If ``Protect`` is false, GopherLua will panic instead of returning an ``error`` value.
   389  
   390  +++++++++++++++++++++++++++++++++++++++++
   391  User-Defined types
   392  +++++++++++++++++++++++++++++++++++++++++
   393  You can extend GopherLua with new types written in Go.
   394  ``LUserData`` is provided for this purpose.
   395  
   396  .. code-block:: go
   397  
   398      type Person struct {
   399          Name string
   400      }
   401  
   402      const luaPersonTypeName = "person"
   403  
   404      // Registers my person type to given L.
   405      func registerPersonType(L *lua.LState) {
   406          mt := L.NewTypeMetatable(luaPersonTypeName)
   407          L.SetGlobal("person", mt)
   408          // static attributes
   409          L.SetField(mt, "new", L.NewFunction(newPerson))
   410          // methods
   411          L.SetField(mt, "__index", L.SetFuncs(L.NewTable(), personMethods))
   412      }
   413  
   414      // Constructor
   415      func newPerson(L *lua.LState) int {
   416          person := &Person{L.CheckString(1)}
   417          ud := L.NewUserData()
   418          ud.Value = person
   419          L.SetMetatable(ud, L.GetTypeMetatable(luaPersonTypeName))
   420          L.Push(ud)
   421          return 1
   422      }
   423  
   424      // Checks whether the first lua argument is a *LUserData with *Person and returns this *Person.
   425      func checkPerson(L *lua.LState) *Person {
   426          ud := L.CheckUserData(1)
   427          if v, ok := ud.Value.(*Person); ok {
   428              return v
   429          }
   430          L.ArgError(1, "person expected")
   431          return nil
   432      }
   433  
   434      var personMethods = map[string]lua.LGFunction{
   435          "name": personGetSetName,
   436      }
   437  
   438      // Getter and setter for the Person#Name
   439      func personGetSetName(L *lua.LState) int {
   440          p := checkPerson(L)
   441          if L.GetTop() == 2 {
   442              p.Name = L.CheckString(2)
   443              return 0
   444          }
   445          L.Push(lua.LString(p.Name))
   446          return 1
   447      }
   448  
   449      func main() {
   450          L := lua.NewState()
   451          defer L.Close()
   452          registerPersonType(L)
   453          if err := L.DoString(`
   454              p = person.new("Steeve")
   455              print(p:name()) -- "Steeve"
   456              p:name("Alice")
   457              print(p:name()) -- "Alice"
   458          `); err != nil {
   459              panic(err)
   460          }
   461      }
   462  
   463  +++++++++++++++++++++++++++++++++++++++++
   464  Terminating a running LState
   465  +++++++++++++++++++++++++++++++++++++++++
   466  GopherLua supports the `Go Concurrency Patterns: Context <https://blog.golang.org/context>`_ .
   467  
   468  
   469  .. code-block:: go
   470  
   471      L := lua.NewState()
   472      defer L.Close()
   473      ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
   474      defer cancel()
   475      // set the context to our LState
   476      L.SetContext(ctx)
   477      err := L.DoString(`
   478        local clock = os.clock
   479        function sleep(n)  -- seconds
   480          local t0 = clock()
   481          while clock() - t0 <= n do end
   482        end
   483        sleep(3)
   484      `)
   485      // err.Error() contains "context deadline exceeded"
   486  
   487  With coroutines
   488  
   489  .. code-block:: go
   490  
   491  	L := lua.NewState()
   492  	defer L.Close()
   493  	ctx, cancel := context.WithCancel(context.Background())
   494  	L.SetContext(ctx)
   495  	defer cancel()
   496  	L.DoString(`
   497  	    function coro()
   498  		  local i = 0
   499  		  while true do
   500  		    coroutine.yield(i)
   501  			i = i+1
   502  		  end
   503  		  return i
   504  	    end
   505  	`)
   506  	co, cocancel := L.NewThread()
   507  	defer cocancel()
   508  	fn := L.GetGlobal("coro").(*LFunction)
   509  
   510  	_, err, values := L.Resume(co, fn) // err is nil
   511  
   512  	cancel() // cancel the parent context
   513  
   514  	_, err, values = L.Resume(co, fn) // err is NOT nil : child context was canceled
   515  
   516  **Note that using a context causes performance degradation.**
   517  
   518  .. code-block::
   519  
   520      time ./glua-with-context.exe fib.lua
   521      9227465
   522      0.01s user 0.11s system 1% cpu 7.505 total
   523  
   524      time ./glua-without-context.exe fib.lua
   525      9227465
   526      0.01s user 0.01s system 0% cpu 5.306 total
   527  
   528  +++++++++++++++++++++++++++++++++++++++++
   529  Sharing Lua byte code between LStates
   530  +++++++++++++++++++++++++++++++++++++++++
   531  Calling ``DoFile`` will load a Lua script, compile it to byte code and run the byte code in a ``LState``.
   532  
   533  If you have multiple ``LStates`` which are all required to run the same script, you can share the byte code between them,
   534  which will save on memory.
   535  Sharing byte code is safe as it is read only and cannot be altered by lua scripts.
   536  
   537  .. code-block:: go
   538  
   539      // CompileLua reads the passed lua file from disk and compiles it.
   540      func CompileLua(filePath string) (*lua.FunctionProto, error) {
   541          file, err := os.Open(filePath)
   542          defer file.Close()
   543          if err != nil {
   544              return nil, err
   545          }
   546          reader := bufio.NewReader(file)
   547          chunk, err := parse.Parse(reader, filePath)
   548          if err != nil {
   549              return nil, err
   550          }
   551          proto, err := lua.Compile(chunk, filePath)
   552          if err != nil {
   553              return nil, err
   554          }
   555          return proto, nil
   556      }
   557  
   558      // DoCompiledFile takes a FunctionProto, as returned by CompileLua, and runs it in the LState. It is equivalent
   559      // to calling DoFile on the LState with the original source file.
   560      func DoCompiledFile(L *lua.LState, proto *lua.FunctionProto) error {
   561          lfunc := L.NewFunctionFromProto(proto)
   562          L.Push(lfunc)
   563          return L.PCall(0, lua.MultRet, nil)
   564      }
   565  
   566      // Example shows how to share the compiled byte code from a lua script between multiple VMs.
   567      func Example() {
   568          codeToShare := CompileLua("mylua.lua")
   569          a := lua.NewState()
   570          b := lua.NewState()
   571          c := lua.NewState()
   572          DoCompiledFile(a, codeToShare)
   573          DoCompiledFile(b, codeToShare)
   574          DoCompiledFile(c, codeToShare)
   575      }
   576  
   577  +++++++++++++++++++++++++++++++++++++++++
   578  Goroutines
   579  +++++++++++++++++++++++++++++++++++++++++
   580  The ``LState`` is not goroutine-safe. It is recommended to use one LState per goroutine and communicate between goroutines by using channels.
   581  
   582  Channels are represented by ``channel`` objects in GopherLua. And a ``channel`` table provides functions for performing channel operations.
   583  
   584  Some objects can not be sent over channels due to having non-goroutine-safe objects inside itself.
   585  
   586  - a thread(state)
   587  - a function
   588  - an userdata
   589  - a table with a metatable
   590  
   591  You **must not** send these objects from Go APIs to channels.
   592  
   593  
   594  
   595  .. code-block:: go
   596  
   597      func receiver(ch, quit chan lua.LValue) {
   598          L := lua.NewState()
   599          defer L.Close()
   600          L.SetGlobal("ch", lua.LChannel(ch))
   601          L.SetGlobal("quit", lua.LChannel(quit))
   602          if err := L.DoString(`
   603          local exit = false
   604          while not exit do
   605            channel.select(
   606              {"|<-", ch, function(ok, v)
   607                if not ok then
   608                  print("channel closed")
   609                  exit = true
   610                else
   611                  print("received:", v)
   612                end
   613              end},
   614              {"|<-", quit, function(ok, v)
   615                  print("quit")
   616                  exit = true
   617              end}
   618            )
   619          end
   620        `); err != nil {
   621              panic(err)
   622          }
   623      }
   624  
   625      func sender(ch, quit chan lua.LValue) {
   626          L := lua.NewState()
   627          defer L.Close()
   628          L.SetGlobal("ch", lua.LChannel(ch))
   629          L.SetGlobal("quit", lua.LChannel(quit))
   630          if err := L.DoString(`
   631          ch:send("1")
   632          ch:send("2")
   633        `); err != nil {
   634              panic(err)
   635          }
   636          ch <- lua.LString("3")
   637          quit <- lua.LTrue
   638      }
   639  
   640      func main() {
   641          ch := make(chan lua.LValue)
   642          quit := make(chan lua.LValue)
   643          go receiver(ch, quit)
   644          go sender(ch, quit)
   645          time.Sleep(3 * time.Second)
   646      }
   647  
   648  '''''''''''''''
   649  Go API
   650  '''''''''''''''
   651  
   652  ``ToChannel``, ``CheckChannel``, ``OptChannel`` are available.
   653  
   654  Refer to `Go doc(LState methods) <http://godoc.org/github.com/yuin/gopher-lua>`_ for further information.
   655  
   656  '''''''''''''''
   657  Lua API
   658  '''''''''''''''
   659  
   660  - **channel.make([buf:int]) -> ch:channel**
   661      - Create new channel that has a buffer size of ``buf``. By default, ``buf`` is 0.
   662  
   663  - **channel.select(case:table [, case:table, case:table ...]) -> {index:int, recv:any, ok}**
   664      - Same as the ``select`` statement in Go. It returns the index of the chosen case and, if that
   665        case was a receive operation, the value received and a boolean indicating whether the channel has been closed.
   666      - ``case`` is a table that outlined below.
   667          - receiving: `{"|<-", ch:channel [, handler:func(ok, data:any)]}`
   668          - sending: `{"<-|", ch:channel, data:any [, handler:func(data:any)]}`
   669          - default: `{"default" [, handler:func()]}`
   670  
   671  ``channel.select`` examples:
   672  
   673  .. code-block:: lua
   674  
   675      local idx, recv, ok = channel.select(
   676        {"|<-", ch1},
   677        {"|<-", ch2}
   678      )
   679      if not ok then
   680          print("closed")
   681      elseif idx == 1 then -- received from ch1
   682          print(recv)
   683      elseif idx == 2 then -- received from ch2
   684          print(recv)
   685      end
   686  
   687  .. code-block:: lua
   688  
   689      channel.select(
   690        {"|<-", ch1, function(ok, data)
   691          print(ok, data)
   692        end},
   693        {"<-|", ch2, "value", function(data)
   694          print(data)
   695        end},
   696        {"default", function()
   697          print("default action")
   698        end}
   699      )
   700  
   701  - **channel:send(data:any)**
   702      - Send ``data`` over the channel.
   703  - **channel:receive() -> ok:bool, data:any**
   704      - Receive some data over the channel.
   705  - **channel:close()**
   706      - Close the channel.
   707  
   708  ''''''''''''''''''''''''''''''
   709  The LState pool pattern
   710  ''''''''''''''''''''''''''''''
   711  To create per-thread LState instances, You can use the ``sync.Pool`` like mechanism.
   712  
   713  .. code-block:: go
   714  
   715      type lStatePool struct {
   716          m     sync.Mutex
   717          saved []*lua.LState
   718      }
   719  
   720      func (pl *lStatePool) Get() *lua.LState {
   721          pl.m.Lock()
   722          defer pl.m.Unlock()
   723          n := len(pl.saved)
   724          if n == 0 {
   725              return pl.New()
   726          }
   727          x := pl.saved[n-1]
   728          pl.saved = pl.saved[0 : n-1]
   729          return x
   730      }
   731  
   732      func (pl *lStatePool) New() *lua.LState {
   733          L := lua.NewState()
   734          // setting the L up here.
   735          // load scripts, set global variables, share channels, etc...
   736          return L
   737      }
   738  
   739      func (pl *lStatePool) Put(L *lua.LState) {
   740          pl.m.Lock()
   741          defer pl.m.Unlock()
   742          pl.saved = append(pl.saved, L)
   743      }
   744  
   745      func (pl *lStatePool) Shutdown() {
   746          for _, L := range pl.saved {
   747              L.Close()
   748          }
   749      }
   750  
   751      // Global LState pool
   752      var luaPool = &lStatePool{
   753          saved: make([]*lua.LState, 0, 4),
   754      }
   755  
   756  Now, you can get per-thread LState objects from the ``luaPool`` .
   757  
   758  .. code-block:: go
   759  
   760      func MyWorker() {
   761         L := luaPool.Get()
   762         defer luaPool.Put(L)
   763         /* your code here */
   764      }
   765  
   766      func main() {
   767          defer luaPool.Shutdown()
   768          go MyWorker()
   769          go MyWorker()
   770          /* etc... */
   771      }
   772  
   773  
   774  ----------------------------------------------------------------
   775  Differences between Lua and GopherLua
   776  ----------------------------------------------------------------
   777  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   778  Goroutines
   779  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   780  
   781  - GopherLua supports channel operations.
   782      - GopherLua has a type named ``channel``.
   783      - The ``channel`` table provides functions for performing channel operations.
   784  
   785  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   786  Unsupported functions
   787  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   788  
   789  - ``string.dump``
   790  - ``os.setlocale``
   791  - ``lua_Debug.namewhat``
   792  - ``package.loadlib``
   793  - debug hooks
   794  
   795  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   796  Miscellaneous notes
   797  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   798  
   799  - ``collectgarbage`` does not take any arguments and runs the garbage collector for the entire Go program.
   800  - ``file:setvbuf`` does not support a line buffering.
   801  - Daylight saving time is not supported.
   802  - GopherLua has a function to set an environment variable : ``os.setenv(name, value)``
   803  
   804  ----------------------------------------------------------------
   805  Standalone interpreter
   806  ----------------------------------------------------------------
   807  Lua has an interpreter called ``lua`` . GopherLua has an interpreter called ``glua`` .
   808  
   809  .. code-block:: bash
   810  
   811     go get github.com/yuin/gopher-lua/cmd/glua
   812  
   813  ``glua`` has same options as ``lua`` .
   814  
   815  ----------------------------------------------------------------
   816  How to Contribute
   817  ----------------------------------------------------------------
   818  See `Guidlines for contributors <https://github.com/yuin/gopher-lua/tree/master/.github/CONTRIBUTING.md>`_ .
   819  
   820  ----------------------------------------------------------------
   821  Libraries for GopherLua
   822  ----------------------------------------------------------------
   823  
   824  - `gopher-luar <https://github.com/layeh/gopher-luar>`_ : Simplifies data passing to and from gopher-lua
   825  - `gluamapper <https://github.com/yuin/gluamapper>`_ : Mapping a Lua table to a Go struct
   826  - `gluare <https://github.com/yuin/gluare>`_ : Regular expressions for gopher-lua
   827  - `gluahttp <https://github.com/cjoudrey/gluahttp>`_ : HTTP request module for gopher-lua
   828  - `gopher-json <https://github.com/layeh/gopher-json>`_ : A simple JSON encoder/decoder for gopher-lua
   829  - `gluayaml <https://github.com/kohkimakimoto/gluayaml>`_ : Yaml parser for gopher-lua
   830  - `glua-lfs <https://github.com/layeh/gopher-lfs>`_ : Partially implements the luafilesystem module for gopher-lua
   831  - `gluaurl <https://github.com/cjoudrey/gluaurl>`_ : A url parser/builder module for gopher-lua
   832  - `gluahttpscrape <https://github.com/felipejfc/gluahttpscrape>`_ : A simple HTML scraper module for gopher-lua
   833  - `gluaxmlpath <https://github.com/ailncode/gluaxmlpath>`_ : An xmlpath module for gopher-lua
   834  - `gluasocket <https://github.com/BixData/gluasocket>`_ : A LuaSocket library for the GopherLua VM
   835  - `gluabit32 <https://github.com/BixData/gluabit32>`_ : A native Go implementation of bit32 for the GopherLua VM.
   836  - `gmoonscript <https://github.com/rucuriousyet/gmoonscript>`_ : Moonscript Compiler for the Gopher Lua VM
   837  - `loguago <https://github.com/rucuriousyet/loguago>`_ : Zerolog wrapper for Gopher-Lua
   838  - `gluacrypto <https://github.com/tengattack/gluacrypto>`_ : A native Go implementation of crypto library for the GopherLua VM.
   839  - `gluasql <https://github.com/tengattack/gluasql>`_ : A native Go implementation of SQL client for the GopherLua VM.
   840  - `purr <https://github.com/leyafo/purr>`_ : A http mock testing tool.
   841  ----------------------------------------------------------------
   842  Donation
   843  ----------------------------------------------------------------
   844  
   845  BTC: 1NEDSyUmo4SMTDP83JJQSWi1MvQUGGNMZB
   846  
   847  ----------------------------------------------------------------
   848  License
   849  ----------------------------------------------------------------
   850  MIT
   851  
   852  ----------------------------------------------------------------
   853  Author
   854  ----------------------------------------------------------------
   855  Yusuke Inuzuka