Help us understand the problem. What is going on with this article?

Go言語のWebフレームワーク「Echo」を使ってみる ①(Hello World的な)

More than 3 years have passed since last update.

すべての記事の一覧はこちら。
Go言語でWebサイトを作ってみる:目次
http://qiita.com/y_ussie/items/8fcc3077274449478bc9

初Qiita投稿になります。

GoのWebフレームワークを使ってみようと思いMartiniやらGinやらを調べていたのですが、Echoがそこそこ新しめのフレームワークで開発も活発なようなので、基本的な使い方を試してみることにしました。

やりたいこと

以下のリクエストを処理する。

GET /

以下のテンプレートを使用して生成したHTMLを返す。

全ページ共通のレイアウトテンプレート

templates/layout.html
<html>
  <head>
    <title>Echo HTML Server Sample</title>
  </head>
  <body>
    <!-- Render the current template here -->
    {{template "content" .}}
  </body>
</html>

コンテンツ毎のテンプレート

templates/hello.html
{{define "content"}}
<h2>Hello {{.}}!</h2>
{{end}}

GET /api/hello

以下のJSONを返す。

{"hello": "world"}

GET /public/css | js | img

静的ファイルを返す。

ということでいろいろと調べながら書いてみた

main.go
package main

import (
    "html/template"
    "io"
    "net/http"

    "github.com/labstack/echo"
    "github.com/labstack/echo/middleware"
)

// レイアウト適用済のテンプレートを保存するmap
var templates map[string]*template.Template

// Template はHTMLテンプレートを利用するためのRenderer Interfaceです。
type Template struct {
}

// Render はHTMLテンプレートにデータを埋め込んだ結果をWriterに書き込みます。
func (t *Template) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
    return templates[name].ExecuteTemplate(w, "layout.html", data)
}

func main() {
    // Echoのインスタンスを生成
    e := echo.New()

    // テンプレートを利用するためのRendererの設定
    t := &Template{}
    e.Renderer = t

    // ミドルウェアを設定
    e.Use(middleware.Logger())
    e.Use(middleware.Recover())

    // 静的ファイルのパスを設定
    e.Static("/public/css/", "./public/css")
    e.Static("/public/js/", "./public/js/")
    e.Static("/public/img/", "./public/img/")

    // 各ルーティングに対するハンドラを設定
    e.GET("/", HandleIndexGet)
    e.GET("/api/hello", HandleAPIHelloGet)

    // サーバーを開始
    e.Logger.Fatal(e.Start(":3000"))
}

// 初期化を行います。
func init() {
    loadTemplates()
}

// 各HTMLテンプレートに共通レイアウトを適用した結果を保存します(初期化時に実行)。
func loadTemplates() {
    var baseTemplate = "templates/layout.html"
    templates = make(map[string]*template.Template)
    templates["index"] = template.Must(
        template.ParseFiles(baseTemplate, "templates/hello.html"))
}

// HandleIndexGet は Index のGet時のHTMLデータ生成処理を行います。
func HandleIndexGet(c echo.Context) error {
    return c.Render(http.StatusOK, "index", "World")
}

// HandleAPIHelloGet は /api/hello のGet時のJSONデータ生成処理を行います。
func HandleAPIHelloGet(c echo.Context) error {
    return c.JSON(http.StatusOK, map[string]interface{}{"hello": "world"})
}

最初はEchoのGuide https://echo.labstack.com/guide を見ながら書き始めましたが、共通レイアウトテンプレートの適用部分などはこちら https://github.com/vitorsvieira/go-gin-boilerplate のGinのサンプルからEcho向けに移植したりしています。

ほぼコメントを読めばわかるコードですが、ポイントは最初に loadTemplates() で事前にレイアウトを適用したテンプレートをmapに突っ込んでいるところと、Template#Render()にてmapからテンプレートを引っ張りだして処理してるところでしょうか。。

Go自体最近勉強中ですのでいろいろと間違ってるところがあるかもしれません。

実行結果

GET /

1.png

GET /api/hello

2.png

今後の展開

  • セッション管理
  • フォームの扱い
  • ファイルアップロード

など。

y_ussie
しがないSEです。 仕事ではC++ばっかり書いてます。 趣味プログラミングでは最近Goに傾倒しています。 ハードウェアも少し。 https://twitter.com/y_ussie
https://ussie.net
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away