GoでMessagePackのコードを生成するパッケージ(msgpackgen)を作りました

3 min read読了の目安(約2800字

MessagePackとは

まず、公式サイトより引用すると...

MessagePackは、効率の良いバイナリ形式のオブジェクト・シリアライズ フォーマットです。JSONの置き換えとして使うことができ、様々なプログラミング言語をまたいでデータを交換することが可能です。しかも、JSONよりも速くてコンパクトです。

また他にも様々なシリアライザがあると思いますが、MessagePackは50以上の言語で利用可能であり導入しやすいのも特徴です。もちろんGoでも使えるパッケージが存在していますが、新しくmsgpackgenをリリースしました。

なぜ作ったのか

これは前段の話がありまして、実は私自身も後続ではありますが、GoでMessagePackのシリアライザを作ってリリースしています(msgpack)。
速いは正義ということで、他ライブラリよりも速く実装できたので私が関与したサービスで使っていたのですが

「ん〜、データをクライアント(フロントエンド)に返すときって、structに詰めた明瞭な型たち(intとかstringとか)を使うだろうし、それって専用のコードある方がより速く処理できるよな〜」
「例えばAPIサーバで、返すべきデータ定義が決まっているものだったら、それを知っているコードのほうが速く処理できるはずだよな〜」

と漠然と思っていました。そこから幾月か経ち、こんな記事を目にしました。

entityからコード自動生成した話 - Money Forward Kessai TECH BLOG

あ、これ使ったら前考えたこと出来るかも...と思い、作り始め出来上がったのがmsgpackgenです。

ベンチマーク

今はこんな感じになっていて、ShamatonGenとsuffixについているものが今回紹介しているものになります。知っている範囲でGo製のMessagePackシリアライザと公式のProtobufJsonをいれて比較してみました。今の所、一番速そうです...!
a

尚、結果が近しいtinylibというパッケージもCode Generator付きのシリアライザです。実装の際に比較対象にしていましたが、そちらよりも簡単にコード生成できるような仕組みにするのも心がけました。
ということで、ぜひお試しいただきたい...!!

使い方 - コード生成

まずはコード生成していきます。Goにはgo generateというコード生成を行う仕組みがあり、ファイルに決められたコメントを記載しておくことで、効力を発揮してくれます。例えばmain.goに

//go:generate go run github.com/shamaton/msgpackgen

と記載し、シェルで

go generate

とすると、main.goがあるディレクトリを含め、再帰的に配下のディレクトリまでコード生成可能な構造体(struct)を検出しコード生成を行います。出力ファイルは1ファイルにまとめられ、デフォルトのファイル名はresolver.msgpackgen.goで生成されます。

生成例:これこうなります

使い方 - シリアライズ

シリアライズを有効にするために、アプリケーションの開始段階などで有効にするメソッドを呼んでおきます。例えばmain.goなどで...

func main() {
	// 登録 (resolver.msgpackgen.goにある)
	RegisterGeneratedResolver()
	
	// http.Serveするなど
	service()
}

シリアライズ/デシリアライズはjsonパッケージのようにMarshal/Unmarshalが用意されています。importにgithub.com/shamaton/msgpackgen/msgpackを追加してください。

func service() {
    v := RegisteredStruct{}
    b, err := msgpack.Marshal(v)
    if err != nil {
        panic(err)
    }
    
    var vv RegisteredStruct
    err = msgpack.Unmarshal(b, &vv)
    if err != nil {
        panic(err)
    }
}

もし、resolver.msgpackgen.goに登録されていないデータが引数に渡された場合はこちらのmsgpackが呼ばれシリアライズされます。

まとめ

msgpackgenを紹介させていただきました。より細かいことはREADMEに書いてありますが、基本は説明したものだけで機能するようになると思います。試していただけると嬉しいです!

ぜひともよろしくお願いします!
summerwars