github.com/tul/gopher-lua@v0.0.0-20181008131706-f6fcaab0c612/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