【Go言語】echoフレームワークの使い方入門

目次

はじめに

本記事では、Go言語で代表的なWebフレームワークであるechoについて、基本的な利用方法についてまとめます。
公式ガイドの内容から抜粋して記載します。

echoについて

echoは高パフォーマンス、拡張可能、軽量なWebフレームワークです。次のような特徴を持っています。

echoの特徴

echoフレームワークの特徴は公式ページで以下のように記載されています。

  • 最適化されたルーター
    • 高度に最適化されたHTTPルーターで、動的メモリの割り当てがなく、経路の優先順位をスマートに決定します。
  • 拡張性がある
    • 頑健でスケーラブルなRESTful APIを構築し、簡単にグループにまとめることができます。
  • 自動TLS
    • Let’s EncryptからTLS証明書を自動的にインストールします。
  • HTTP/2
    • HTTP/2をサポートすることでスピードを改善し、より良いユーザ体験を提供します。
  • ミドルウェア
    • 多くの組み込みミドルウェアを利用でき、独自のミドルウェアを定義する事もできます。ミドルウェアはルート(root)、グループ、ルート(route)レベルで設定できます。
  • Data Binding
    • JSON、XML、form-dataなど、HTTPリクエストペイロードのデータバインディング。
  • Data Rendering
    • JSON、XML、HTML、File、Attachment、Inline Stream、Blobなど、様々なHTTPレスポンスを送信するAPIです。
  • Templates
    • 任意のテンプレートエンジンを使ったテンプレートレンダリング。
  • 拡張可能
    • カスタマイズされたセントラルHTTPエラーハンドリング。容易に拡張可能なAPI。

echoの使い方

公式ガイドの内容を抜粋して実装を進めていきます。

インストール

EchoをインストールするにはGO v1.13以上が必要です。Go v1.12ではサポートが限られており、一部のミドルウェアが利用できません。プロジェクトフォルダが$GOPATHの外にあることを確認してください。

$ mkdir myapp && cd myapp
$ go mod init myapp
$ go get github.com/labstack/echo/v4

動作させる

まずは簡易的に動作させてみます。以下の手順で簡単にAPIを作成することができます。

  1. Echo#New() (e *Echo)でインスタンスを作成
  2. Echo#GET(path string, h HandlerFunc, m ...MiddlewareFunc) *Route でルーティング設定
  3. Echo#Start(address string) errorでサーバーをスタート

下記の例では、パス/にGETでアクセスするとHello World!の文字列を返却するようにルーティング設定しています。実際にブラウザでhttp://localhost:1323/にアクセスするとHello, World!の文字が表示され、簡易的なAPIサーバとして動作していることがわかります。

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"))
}

Routing

上記の項目で既に利用しましたが、echoではEcho.Any(path string, h Handler)の形式で全てのHTTPメソッドのハンドラーを登録することができます。

// Handlers
func createUser(c echo.Context) error {
}

func findUser(c echo.Context) error {
}

func updateUser(c echo.Context) error {
}

func deleteUser(c echo.Context) error {
}

// Routes
e.POST("/users", createUser)
e.GET("/users", findUser)
e.PUT("/users", updateUser)
e.DELETE("/users", deleteUser)

また、Echo#Group(prefix string, m ...Middleware) *Groupを利用して、共通のプレフィックスを持つルートをグループ化する事もできます。下記の例では共通のプレフィックス/adminを持つルートをグループ化し、そのグループに対してルーティング設定しています。そのため、/admin/users/new/admin/users/:idがルートとして設定されます。

g := e.Group("/admin")
g.GET("/users/new", createUser)
g.GET("/users/:id", findUser)

Path Parameters

ルーティング設定に:name の形式でパスを設定すると、パスパラメータとして登録することができます。パスパラメータを受け取る際は、Context#Param(name string) stringを利用します。
下記の例では、ブラウザでhttp://localhost:1323/users/Joeにアクセスすると、Joeの文字が表示されます。

e.GET("/users/:id", func(c echo.Context) error {
  name := c.Param("id")
  return c.String(http.StatusOK, id)
})

Query Parameters

クエリパラメータを受け取るには、Context#QueryParam(name string)を利用します。
下記の例では、ブラウザでhttp://localhost:1323/show?team=x-men&member=wolverineにアクセスすると、team:x-men, member:wolverineと表示されます。

//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)
}

Form application/x-www-form-urlencoded

Content-Typeがapplication/x-www-form-urlencodedのデータを受け取るには、Context#FormValue(name string)を利用します。

// e.POST("/save", save)
func save(c echo.Context) error {
	// Get name and email
	name := c.FormValue("name")
	email := c.FormValue("email")
	return c.String(http.StatusOK, "name:" + name + ", email:" + email)
}

次のコマンドを実行すると、受け取れていることが確認できます。

$ curl -F "name=Joe Smith" -F "email=joe@labstack.com" http://localhost:1323/save
// => name:Joe Smith, email:joe@labstack.com

Handling Request

Context#Bind(i interface{})を用いることで、jsonxmlformqueryなどのペイロードを、リクエストヘッダーのContent-Typeに基づいてGoの構造体にバインドすることができます。

また、Context#JSON(code int, i interface{})や、Context#XML(code int, i interface{})を利用することで、JSONおよびXMLにエンコードしてレスポンスコードと一緒にレスポンスを送信することができます。

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)
})

Static Content

静的コンテンツを提供するには、Echo#Static(prefix, root string)を利用します。
下記の例では、パスが/static/*のassetsディレクトリから任意のファイルを提供します。例えば、/static/js/main.jsへのリクエストは、assets/js/main.jsファイルをフェッチして提供します。

e.Static("/static", "assets")

また、Echo#File(path, file string)を利用することで静的ファイルを提供できます。
下記の例では、パス/にアクセスするとpublic/index.htmlを返却します。

e.File("/", "public/index.html")

Middleware

ミドルウェアとは、HTTPリクエスト・レスポンスサイクルの中で連鎖している機能で、Echo#Contextへのアクセス権を持ち、特定のアクションを実行するために使用されます。例えば、すべてのリクエストをログに記録したり、リクエスト数を制限したりすることができます。

ハンドラは、すべてのミドルウェアの実行が終了した後、最後に処理されます。

また、Echo#Use()を使用して登録されたミドルウェアは、Echo#Use()が呼び出された後に登録されたパスに対してのみ実行されます。

下記の例では、middleware.Logger()middleware.Recover()はRoot Levelで設定しているため、全てのリクエストに対して適用されます。一方で、middleware.BasicAuth()はグループe.Group("/admin")に対して設定しているため、/adminから始まるリクエストにのみ適用されます。

最後のtrack変数は、自作したカスタムミドルウェアを代入しています。

// Root level middleware
e.Use(middleware.Logger())
e.Use(middleware.Recover())

// Group level middleware
g := e.Group("/admin")
g.Use(middleware.BasicAuth(func(username, password string, c echo.Context) (bool, error) {
  if username == "joe" && password == "secret" {
    return true, nil
  }
  return false, nil
}))

// Route level middleware
track := func(next echo.HandlerFunc) echo.HandlerFunc {
	return func(c echo.Context) error {
		println("request to /users")
		return next(c)
	}
}
e.GET("/users", func(c echo.Context) error {
	return c.String(http.StatusOK, "/users")
}, track)

まとめ

本記事では公式ガイドに沿ってechoの基本的な利用方法についてまとめました。
様々な種類のあるmiddlewareの使い方など、echoの詳しい利用方法についても今後記事にできればと思います。
閲覧いただきありがとうございました。

他のパッケージやGo言語における基本的な利用方法についても記事を書いていますので、もし興味がありましたらご参照ください。

【Go言語】ファイル/ディレクトリ操作方法 – 基本
【Go言語】database/sqlパッケージによるデータベース操作入門 – sqlite3
【Go言語】encoding/jsonパッケージでJSONをパースする
【Go言語】net/httpパッケージでAPIリクエストを送信する

よかったらシェアしてね!

コメント

コメントする

CAPTCHA


目次
閉じる