LoginSignup
0
2

More than 5 years have passed since last update.

Go で EventEmitter のコードを自動生成するツールを作った

Last updated at Posted at 2016-11-05

前置き

Go で EventEmitter/Dispatcher 的なことをしたい場合、 emissiongo-pubsub などの既存のライブラリを使うのが最も手っ取り早いと思いますが、

golang で event emitter/dispatcher 的なもの | tech - 氾濫原

リフレクションで型変換は隠蔽されているが、もしリスナーとエミッターとで型が食い違っていると、実行時エラーになる。

「イベント名」というパラメータが存在せず、型の選択によって自動的にディスパッチされる。よって型がマッチしなければリスナーは実行されないので、原理的に型変換の実行時エラーは発生しない (もし間違えた場合単に実行時になって「呼ばれない」ことに気付く)

で解説されている通り、上記ライブラリではコードにミスがあった場合、実行時でないとその問題が露見しません。

やはり静的型付け言語を書いている以上、コンパイル時にミスは発見できてほしい…ということで、コンパイル時に型チェックできるような EventEmitter を go generate で自動生成するツールがあったら、それなりに需要があるんじゃないだろうかと思い、作ってみました。

インストール

$ go get -u github.com/shiwano/genem

使い方

ヘルプテキストをべたり。

genem

Usage:
  genem [options] <file>
  genem -h | --help
  genem --version

Options:
  -n, --emitter-name string      Specify the event emitter type name (default: EventEmitter).
  -o, --output-file-name string  Specify the output file name (default: event_emitter.go).
  -p, --print                    Print the generated code without file output.
  -h, --help                     Output help information.
  -v, --version                  Output version.

このツールは、指定した Go のファイルから lower camel case で最後に Event で終わる名前の struct を探してきて(例: fooEvent)、その struct の定義に対応した EventEmitter のコードを自動生成します。

例えば

以下のようなファイルを作り、

//go:generate genem -n Emitter -o emitter.go $GOFILE

package event

type fooEvent struct {
    bar string
    baz int
}

type quxEvent struct {
    quux float32
}

go generate をすると、そのファイルのあるディレクトリに emitter.go というファイル名で以下のようなコードが自動生成されます。

package event

type Emitter struct {}

func NewEmitter() *Emitter

func (_e *Emitter) EmitFooEvent(bar string, baz int)
func (_e *Emitter) AddFooEventListener(listener func(bar string, baz int))
func (_e *Emitter) AddFooEventListenerOnce(listener func(bar string, baz int))
func (_e *Emitter) RemoveFooEventListener(listener func(bar string, baz int))

func (_e *Emitter) EmitQuxEvent(quux float32)
func (_e *Emitter) AddQuxEventListener(listener func(quux float32))
func (_e *Emitter) AddQuxEventListenerOnce(listener func(quux float32))
func (_e *Emitter) RemoveQuxEventListener(listener func(quux float32))

生成された EventEmitter は、以下のような感じで使えます。

package main

import (
    "fmt"
    "example.com/event"
)

func main() {
    e := event.NewEmitter()
    e.AddFooEventListener(func(bar string, baz int) {
        fmt.Println("foo: ", bar, baz) // Output: "foo: bar 3"
    })
    e.EmitFooEvent("bar", 3)
}
0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2