github.com/qiniu/gopher-lua@v0.2017.11/README.rst (about)

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