LoginSignup
250

More than 5 years have passed since last update.

Go Web Frameworks 比較

Last updated at Posted at 2015-12-11

Go言語にはいろいろなWebフレームワークが存在して、はっきりとしたデファクトスタンダードが決まっていません。

しいて言えば標準パッケージの net/http がデファクトですが、世の中ではそこに機能不足を感じた人たちが多くのフレームワークを開発しています。

そこで、いくつかのフレームワークを取り上げて、簡単なベンチマークと、それぞれのフレームワークでのいわゆるHello Worldの書き方をまとめておきます。

これによって、フレームワーク選びの参考になればと思います。

対象

Revel、Beego、Kochaなど、見かけたが入れていないものがいくつかあります。コマンドでスケルトンを作るもの、net/http の Handler interface を満たさないものは除外しました。

追加してくれる方はコメントか編集リクエストをお願いします!

Negroni あたりは入れたいですね。

個人的な感想

後半を読み飛ばしたい人のために、個人的な好みでオススメをあげておきますと、GinかEchoです。パフォーマンスも良く、いろいろ便利メソッドもあるのでよさそうです。

もっと薄いものが欲しい人は net/http が良いでしょう。

ベンチマーク

GET /gopher のリクエストを送って Hello, gopher! を返す単純なコードを書いて計測します。

ベンチマークは https://github.com/najeira/go-frameworks-benchmark にあります。フレームワークを追加したい方、ベンチマークの種類を増やしたい方、ぜひ Pull Request をお願いいたします。

なお、大量のハンドラがある場合のルーティングについて知りたい人は https://github.com/julienschmidt/go-http-routing-benchmark も参照してください。

時間

ns/op
Gin 734
Echo 879
Kami 1237
Goji 1299
Bone 1463
http 1854
Gocraft 1915
Gorilla 3944
Martini 5823

GinとEchoが優秀です。Martiniは内部でリフレクションを使っているためか遅いですが、それでもナノ秒の単位ですので、ここがアプリケーションのボトルネックになることはなさそうです。

allocs

allocs/op
Gin 3
Echo 5
Goji 6
Bone 7
http 7
Kami 9
Gocraft 12
Gorilla 15
Martini 22

ここでもGinとEchoが優秀です。とはいえ、GoのGCは進歩して性能が上がっていること、アプリケーション内でのアロケーションが支配的になるでしょうから、ここも大きな差はないといってよいでしょう。

GitHub

Stars Contributors
Martini 7995 93
Gin 4857 64
Goji 2888 17
Echo 2698 28
Gorilla 1808 27
Gocraft 918 11
Bone 823 11
Kami 127 4

Martiniは歴史もあり、初期に多くのStarsを獲得、またContributeも多いようです。次いでGin。また、Echoは2015年スタートですが、かなりの勢いでStarsを獲得しています。

コード

コード全体は https://github.com/najeira/go-frameworks-benchmark を見てください。ここでは雰囲気を把握してもらえれば。

Bone

m := bone.New()
m.Get("/:name", handler)
func handler(w http.ResponseWriter, r *http.Request) {
  name := bone.GetValue(r, "name")
  fmt.Fprintf(w, "Hello, %s", name)
}

Echo

m := echo.New()
m.Get("/:name", handler)
func handler(c *echo.Context) error {
  name := c.Param("name")
  return c.String(200, "Hello, %s", name)
}

Gin

m := gin.New()
m.GET("/:name", handler)
func handler(c *gin.Context) {
  name := c.Param("name")
  c.String(200, "Hello, %s", name)
}

Goji

m := goji.New()
m.Get("/:name", handler)
func handler(c goji.C, w http.ResponseWriter, r *http.Request) {
  name := c.URLParams["name"]
  fmt.Fprintf(w, "Hello, %s", name)
}

Gocraft

m := gocraft.New(ctx{})
m.Get("/:name", (*ctx).handler)
func (c *ctx) handler(w gocraft.ResponseWriter, r *gocraft.Request) {
  name := r.PathParams["name"]
  fmt.Fprintf(w, "Hello, %s", name)
}

Gorilla

m := goriila.NewRouter()
m.HandlerFunc("/{name}", handler)
func handler(w http.ResponseWriter, r *http.Request) {
  name := gorilla.Vars(r)["name"]
  fmt.Fprintf(w, "Hello, %s", name)
}

Kami

m := kami.New()
m.Get("/:name", handler)
func handler(c context.Context, w http.ResponseWriter, r *http.Request) {
  name := kami.Param(c, "name")
  fmt.Fprintf(w, "Hello, %s", name)
}

Martini

m := martini.Classic()
m.Get("/:name", handler)
func handler(w http.ResponseWriter, p *martini.Params) string {
  name := p["name"]
  return fmt.Sprintf("Hello, %s", name)
}

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
250