お世話になっております。
しゃまとんです。

GoのMessagePackパッケージ、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に書いてありますが、基本は説明したものだけで機能するようになると思います。試していただけると嬉しいです!

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