はじめに
GoのWebフレームワークecho入門。
公式ドキュメントに書いてあることをほんのちょっとだけ深ぼってみる。
Quick Start
なにはともあれgo get
go get -u github.com/labstack/echo/...
package main
import (
	"net/http"
	"github.com/labstack/echo"
)
func main() {
	e := echo.New()
	e.GET("/", func(c echo.Context) error {
		return c.String(http.StatusOK, "Hello, World!")
	})
	e.Logger.Fatal(e.Start(":1323"))
}
ブラウザからhttp://localhost:1323に接続するとHello, World!という文字列が表示されることが確認できます。
echo.New()はこのフレームワークの核となるEchoインスタンスを作成します。
詳細を追うことはしませんが、*http.Serverやnet.Listener等をラップしているようです。
(*Echo) GETはhttp.HandleFuncと同じような役割を担うメソッドです。HTTPメソッドとリクエストを受け取るURLパターン、それに対応するためのハンドラを登録します。
(*Echo) GETで登録されたハンドラはGETメソッドで送信されたリクエストだけを受け取ります。http://localhost:1323に対してPOSTメソッドでリクエストが送信された場合、そのレスポンスはMethod Not Allowedです。
echo.Contextは現在のHTTPリクエスト状況を表しています。http.ResponseWriterや*http.Requestをラップしており、リクエスト内容他、諸々の情報を保持しています。
echo.Context represents the context of the current HTTP request. It holds request and response reference, path, path parameters, data, registered handler and APIs to read request and write response.
(*context) Stringはステータスコードとともに文字列をレスポンスに書き込むためのメソッドです。Content-Type の MIMEType は text/plain 、文字コードは UTF-8 が指定されます。
(*Echo) StartはHTTPサーバーを開始するためのメソッドです。指定されたアドレスへのリクエストを待ち受け開始します。実質http.ListenAndServe。
Routing
e.POST("/users", saveUser)
e.GET("/users/:id", getUser)
e.PUT("/users/:id", updateUser)
e.DELETE("/users/:id", deleteUser)
上の例では無名関数をハンドラとして登録しましたが、func(echo.Context) errorという型さえ満たせば任意の関数名でハンドラを登録することが出来ます。
ルーティングの機能としては見たままですね。HTTPメソッド、URLパターン、ハンドラを登録します。:idのように書くと、この部分がプレースホルダーになります。
Path Parameters
// e.GET("/users/:id", getUser)
func getUser(c echo.Context) error {
  	// User ID from path `users/:id`
  	id := c.Param("id")
	return c.String(http.StatusOK, id)
}
(*context) Paramで指定したプレースホルダーから文字列を取り出すことが出来ます。http://localhost:1323/users/JoeにGETメソッドでリクエストを投げると、変数idにJoeという文字列が格納されます。
http://localhost:1323/users/1のようにプレースホルダー部分が数値であったとしても、(*context) Paramは文字列を返すメソッドなので、構造体やDB等と結びつける場合は注意が必要です。
Query Parameters
//e.GET("/show", show)
func show(c echo.Context) error {
	// Get team and member from the query string
	team := c.QueryParam("team")
	member := c.QueryParam("member")
	return c.String(http.StatusOK, "team:" + team + ", member:" + member)
}
(*context) QueryParamでクエリパラメーターを取得することが出来ます。語ることもないですね...。
http://localhost:1323/show?team=x-men&member=wolverineにGETメソッドでリクエストを投げるとteam:x-men, member:wolverineの文字列が返ってきます。
type User struct {
	Name  string `json:"name" xml:"name" form:"name" query:"name"`
	Email string `json:"email" xml:"email" form:"email" query:"email"`
}
e.POST("/users", func(c echo.Context) error {
	u := new(User)
	if err := c.Bind(u); err != nil {
		return err
	}
	return c.JSON(http.StatusCreated, u)
	// or
	// return c.XML(http.StatusCreated, u)
})
構造体に対して上記のようにタグ付けをすることで、リクエストのContent-Typeとそのキーに基づいてデータを紐付けるが出来ます。(*context) Bindの使用方法はとても簡単で、タグ付けが行われている構造体のゼロ値のポインタを引数に取るだけです。 application/json や application/x-www-form-urlencoded で該当の値が送られてきた場合、よしなに構造体へのデータ格納を行ってくれます。
(*context) JSONが初めて出てきましたが機能としては(*context) Stringと大差はありません。構造体やマップ等を渡せばjsonへのエンコードを行い、ステータスコードとともにレスポンスへ書き込みます。
おわりに
今回はガイドの1ページ目に記載されている本当に基礎的な機能だけを試してみましたが、他にも色々な機能が提供されていて使い勝手が良さそうです。まだまだ使いこなせてないので色々試していきたい。
Echo High performance, extensible, minimalist Go web framework
とりあえずMiddlewareやValidator機能を試しますかね...
