先日公開した GopherLua ですが。
GopherLuaはLuaなので、ホスト言語との親和性を重視しております。GolangなのにGoroutine関係のサポートがないとだめでしょ!ということで、とりあえずですが、channelを扱えるようにしました。
これもまたReadmeに書いてありますが、以下のように使います。 selectも使えますし、GolangとLuaの間で縦横無尽にメッセージ通信できます。
1func receiver(ch, quit chan lua.LValue) {
2 L := lua.NewState()
3 defer L.Close()
4 L.SetGlobal("ch", lua.LChannel(ch))
5 L.SetGlobal("quit", lua.LChannel(quit))
6 if err := L.DoString(`
7 local exit = false
8 while not exit do
9 channel.select(
10 {"|<-", ch, function(ok, v)
11 if not ok then
12 print("channel closed")
13 exit = true
14 else
15 print("received:", v)
16 end
17 end},
18 {"|<-", quit, function(ok, v)
19 print("quit")
20 exit = true
21 end}
22 )
23 end
24 `); err != nil {
25 panic(err)
26 }
27}
28
29func sender(ch, quit chan lua.LValue) {
30 L := lua.NewState()
31 defer L.Close()
32 L.SetGlobal("ch", lua.LChannel(ch))
33 L.SetGlobal("quit", lua.LChannel(quit))
34 if err := L.DoString(`
35 ch:send("1")
36 ch:send("2")
37 `); err != nil {
38 panic(err)
39 }
40 ch <- lua.LString("3")
41 quit <- lua.LTrue
42}
43
44func main() {
45 ch := make(chan lua.LValue)
46 quit := make(chan lua.LValue)
47 go receiver(ch, quit)
48 go sender(ch, quit)
49 time.Sleep(3 * time.Second)
50}
こんな感じですね。Luaと同じくState自体はスレッドセーフではないので、goroutineごとにStateをもってChannelで通信します。
実装について
迷ったんですが、channelは 基本型 として実装しています。 ユーザーデータ型でもよかったんですが、channelはGolangの特徴の一つですし、基本型にしたほうが親和性がよいので。
あと、内部的にはリフレクションなのでそんなに性能はよくないかもしれません。
よければ使ってみてください
実装してみたものの、正直私は職業プログラマでなく趣味プログラマなのであんまり使うシーンがないです。なんかいい使いどころがあれば使ってみてください。