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