2019年4月11日木曜日

golang echo 超入門

概要

Gin より早いと噂の echo を試してみました
とりあえず公式のチュートリアルを試してみました

環境

  • macOS 10.14.4
  • golang 1.11.5
    • echo 4.0.0

インストール

  • go get -u github.com/labstack/echo/...

Getting Started

  • mkdir $GOPATH/src/github.com/hawksnowlog/echo_test
  • vim $GOPATH/src/github.com/hawksnowlog/echo_test/main.go
package main

import (
    "github.com/labstack/echo"
    "net/http"
)

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"))
}
  • go fmt github.com/hawksnowlog/echo_test
  • go build github.com/hawksnowlog/echo_test
  • ./echo_test
  • curl localhost:1323

で「Hello, World!」が返ってきます

Tips

Github にある README.md のサンプルで実行するとうまく動作しませんでした
dep init すると Package is required by (root) となりうまくインストールできなかったので諦めました

ルーティング

好きなルーティングを追加します

package main

import (
    "github.com/labstack/echo"
    "net/http"
)

func getHandler(c echo.Context) error {
    return c.String(http.StatusOK, "Hello, World!")
}

func hogeHandler(c echo.Context) error {
    return c.String(http.StatusOK, c.Param("path"))
}

func main() {
    e := echo.New()
    e.GET("/", getHandler)
    e.GET("/hoge/:path", hogeHandler)
    e.Logger.Fatal(e.Start(":1323"))
}

必要な数だけ e.GET で追加すれば OK です
c.Param で URL の情報にアクセスできます

  • curl localhost:1323/hoge/fuga

クエリパラメータを取得する

先程は URL を取得しました
今度はクエリとして送信されたパラメータを取得します

package main

import (
    "github.com/labstack/echo"
    "net/http"
)

func getHandler(c echo.Context) error {
    return c.String(http.StatusOK, "Hello, World!")
}

func hogeHandler(c echo.Context) error {
    return c.String(http.StatusOK, c.QueryParam("key"))
}

func main() {
    e := echo.New()
    e.GET("/", getHandler)
    e.GET("/hoge", hogeHandler)
    e.Logger.Fatal(e.Start(":1323"))
}

以下のようにクエリパラメータを付与してリクエストすると value が取得できます

  • curl localhost:1323/hoge?key=value

ちなみに WebUI などからフォーム情報を受け取る場合は c.FormValue を使用します (curl だと -F オプション)

HTML を返却する

Web ページを作成する場合に使います

package main

import (
    "fmt"
    "github.com/labstack/echo"
    "net/http"
)

func htmlHandler(c echo.Context) error {
    return c.HTML(http.StatusOK, fmt.Sprintf("<h1>Hello %s</h1>", c.Param("name")))
}

func main() {
    e := echo.New()
    e.GET("/:name", htmlHandler)
    e.Logger.Fatal(e.Start(":1323"))
}

c.HTML を使います
単純にレスポンスヘッダの Content-Typetext/html; charset=UTF-8 になります

複数の Content-Type に対応する

例えば application/jsonapplication/xml に同時に対応することができるハンドラを定義することができます

例えば application/json であれば以下のように送信できます

  • curl -v -XPOST -H 'Content-Type: application/json' -d '{"name":"hawk","age":10}' localhost:1323

application/xml であれば以下です

  • curl -v -XPOST -H 'Content-Type: application/xml' -d '<User><name>hawk</name><age>20</age></User>' localhost:1323

1 つのハンドラで複数のメディアタイプに対応できるのは便利です

静的ファイルの配信

  • mkdir public
  • cp icon.png public
package main

import (
    "github.com/labstack/echo"
)

func main() {
    e := echo.New()
    e.Static("/img", "./public")
    e.Logger.Fatal(e.Start(":1323"))
}

e.Static を使えば OK です

ミドルウェア

「echo と言えば」という機能かもしれません
豊富なミドルウェア機能がありロギングや認証を簡単に実装することができます
また before/after 処理なども実装できます

package main

import (
    "github.com/labstack/echo"
    "github.com/labstack/echo/middleware"
    "net/http"
)

func main() {
    e := echo.New()

    // logging
    e.Use(middleware.Logger())
    e.Use(middleware.Recover())
    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)

    // basic auth
    g := e.Group("/admin")
    g.Use(middleware.BasicAuth(func(username, password string, c echo.Context) (bool, error) {
        if username == "hawksnowlog" && password == "secret" {
            return true, nil
        }
        return false, nil
    }))
    g.GET("/users", func(c echo.Context) error {
        return c.String(http.StatusOK, "/admin/users")
    }, track)

    e.Logger.Fatal(e.Start(":1323"))

}

上記はロギングとベーシック認証を実装したサンプルです
まずロギングですがロギングは基本的にどのリクエストに対しても適用したいので e.Use(middleware.Logger()) でグローバルな設定を入れます
そして各ルーティングごとに個別に処理したい場合は e.GET の最後の引数に func(next echo.HandlerFunc) echo.HandlerFunc を持つ関数を指定して上げあればそれがリクエストの前に処理されるようになります
なので、そこでルーティングごとに必要なロギングなどをすれば OK です

次はベーシック認証です
これは middleware.BasicAuth を使います
認証が成功した場合は true, nil を返します
false, nil が返った場合は {"message":"Unauthorized"} が返ります
上記では Group に対してベーシック認証を掛けています
ベーシック認証をしないとアクセスできないルーティングを登録したい場合は Group に対してルーティングを追加してあげましょう

最後に

echo に入門してみました
機能がかなり豊富なのとパフォーマンスも Gin に比べて良いということで流行っているようです
記述力も減らせるのでサクサク実装できる感もあり良いと思います

あと気になったのはテンプレートの扱いやエラーハンドリングなどですがその辺りも普通に使えると思います
わからないことがあれば参考サイトにもある公式のドキュメントを見れば大抵は解決すると思います 

参考サイト

0 件のコメント:

コメントを投稿