michimani.net

Go の Web アプリケーションフレームワーク Revel を試してみた

2020-08-20

Go 歴半年くらいで、主に Serverless Framework で Lambda 関数を書くという用途で使っています。今回は Go の Web アプリケーションフレームワーク Revel を触ってみようということで、公式のチュートリアルをやってみます。

目次

概要

Go の Web アプリケーションフレームワークである Revel の公式チュートリアルを一通りやってみます。

Go のバージョンは 1.14.4 です。

$ go version
go version go1.14.4 darwin/amd64

公式チュートリアル

ここからは、 Revel の公式チュートリアルをやっていきます。

インストール

まずは Revel フレームワークと Revel コマンドをインストールします。

$ go get github.com/revel/revel
$ go get github.com/revel/cmd/revel

ヘルプとバージョンを確認しておきます。

$ revel --help
Usage:
  revel [OPTIONS] <command>

Application Options:
  -v, --debug                If set the logger is set to verbose
      --historic-run-mode    If set the runmode is passed a string not json
      --historic-build-mode  If set the code is scanned using the original parsers, not the go.1.11+
  -X, --build-flags=         These flags will be used when building the application. May be specified multiple times, only applicable for Build, Run, Package, Test commands
      --gomod-flags=         These flags will execute go mod commands for each flag, this happens during the build process

Help Options:
  -h, --help                 Show this help message

Available commands:
  build
  clean
  new
  package
  run
  test
  version

$ revel version
Revel executing: displays the Revel Framework and Go version
Revel Framework	:	Unknown	(1.0.0 remote master branch)
Revel Cmd	:	1.0.0	(1.0.0 remote master branch)
Revel Modules	:	Unknown	(1.0.0 remote master branch)


Go Location:/usr/local/bin/go

go version go1.14.4 darwin/amd64

アプリケーション作成

続いて、 my-app という名前の Revel アプリケーションを作成します。

$ revel new -a my-app
Revel executing: create a skeleton Revel application
Your application has been created in:
   /Users/hoge/Projects/go-revel/my-app

You can run it with:
   revel run -a  my-app

作成が完了すると、下記のようなディレクトリ構造が作られます。

$ tree -a -L 2
.
├── .gitignore
├── README.md
├── app
│   ├── controllers
│   ├── init.go
│   ├── routes
│   ├── tmp
│   └── views
├── conf
│   ├── app.conf
│   └── routes
├── go.mod
├── go.sum
├── messages
│   └── sample.en
├── none
├── public
│   ├── css
│   ├── fonts
│   ├── img
│   └── js
├── target
│   └── app
└── tests
    └── apptest.go

起動

revel run コマンドでアプリケーションを起動します。

$ cd my-app
$ revel run -a my-app
Revel executing: run a Revel application
WARN  19:51:15 harness.go:175: No http.addr specified in the app.conf listening on localhost interface only. This will not allow external access to your application 
Changed detected, recompiling
Parsing packages, (may require download if not cached)... Completed
INFO  19:51:25    app     run.go:34: Running revel server                      
INFO  19:51:25    app   plugin.go:9: Go to /@tests to run the tests.           
Revel engine is listening on.. localhost:59472
Revel proxy is listening, point your browser to : 9000

Time to recompile 10.823098593s

コンパイルが完了したあと http://localhost:9000 にアクセスすると、ページが表示されます。

Hello world

右に見えている三角アイコンをクリックすると、デバッグ情報を確認することができます。

Hello world debug

ちなみに Revel では Go のプログラムを変更した時点で自動で再コンパイルが実行されます。

リクエストの処理フロー

では、実際のリクエストが処理される流れを見てみます。

ルーティング

まず、リクエストのルーティングは conf/routes で設定します。

# Routes Config
#
# This file defines all application routes (Higher priority routes first)
#

module:testrunner
# module:jobs


GET     /                                       App.Index

App.Index とは、対応するコントローラーのメソッドを表します。

コントローラー

前述の通り、 conf/routes 内でルーティングに対応するコントローラーのメソッドが指定されています。 App.Index とは app/controllers/app.go 内の Index() メソッドを指します。

package controllers

import (
	"github.com/revel/revel"
)

type App struct {
	*revel.Controller
}

func (c App) Index() revel.Result {
	return c.Render()
}

テンプレートファイル

このルーティングに対応するテンプレートファイルは app/views/App/Index.html となります。

{{set . "title" "Home"}}
{{template "header.html" .}}

<header class="jumbotron" style="background-color:#A9F16C">
  <div class="container">
    <div class="row">
      <h1>It works!</h1>
      <p></p>
    </div>
  </div>
</header>

<div class="container">
  <div class="row">
    <div class="span6">
      {{template "flash.html" .}}
    </div>
  </div>
</div>

{{template "footer.html" .}}

コントローラーからテンプレートへのデータ渡し

コントローラーからテンプレートへデータを渡すには、コントローラーとテンプレートをそれぞれ次のように変更します。

Aloha World

Hello World アプリを作ってみる

続いて、簡単なフォームを用いたアプリケーションを作成してみます。

テンプレートファイルの変更・追加

既存のテンプレートファイル app/views/App/Index.html に下記のフォームを追加します。

  <div class="container">
    <div class="row">
      <div class="span6">
        {{template "flash.html" .}}
+       <form action="/App/Hello" method="GET">
+         <input type="text" name="myName" /><br/>
+         <input type="submit" value="Say hello!" />
+       </form>
      </div>
    </div>
  </div>
  
  {{template "footer.html" .}}

そして、フォーム送信後に表示されるページのテンプレートファイルを、下記の内容で app/views/App/Hello.html という名前で作成します。

{{set . "title" "Hello page"}}
{{template "header.html" .}}

<h1>Hello {{.myName}}</h1>
<a href="/">Back to form</a>

{{template "footer.html" .}}

コントローラーにメソッド追加

続いて、コントローラー app/controllers/app.go に下記のメソッドを追加します。

func (c App) Hello(myName string) revel.Result {
    return c.Render(myName)
}

ルーティングの追加

最後に、 conf/routes にルーティングを追加します。

  GET     /                                       App.Index
+ GET     /App/Hello                              App.Hello

これで準備が整ったので、フォームに値を送信してみます。

input name
send name

バリデーションの追加

今作ったフォームにバリデーションを追加してみます。バリデーション項目としては、必須チェックと最低文字数チェックです。

まずはコントローラー app/controllers/app.goHello() メソッドを次のように変更します。

  func (c App) Hello(myName string) revel.Result {
+ 	c.Validation.Required(myName).Message("Your name is required!")
+ 	c.Validation.MinSize(myName, 3).Message("Your name is not long enough!")
+ 
+ 	if c.Validation.HasErrors() {
+ 		c.Validation.Keep()
+ 		c.FlashParams()
+ 		return c.Redirect(App.Index)
+ 	}
  
  	return c.Render(myName)
  }

エラーメッセージの表示は、テンプレートファイル app/views/App/Index.html にインポートされている app/views/flash.html 内で行われます。

{{if .flash.success}}
<div class="alert alert-success">
	{{.flash.success}}
</div>
{{end}}

{{if or .errors .flash.error}}
<div class="alert alert-danger">
	{{if .flash.error}}
		{{.flash.error}}
	{{end}}
	<ul style="margin-top:10px;">
		{{range .errors}}
			<li>{{.}}</li>
		{{end}}
	</ul>
</div>
{{end}}

そして、フォーム部分を次のように変更します。

  <form action="/App/Hello" method="GET">
-   <input type="text" name="myName" /><br/>
+   {{with $field := field "myName" .}}
+     <input type="text" name="{{$field.Name}}" value="{{$field.Flash}}"/><br/>
+   {{end}}
    <input type="submit" value="Say hello!" />
  </form>
validation error

まとめ

Go の Web アプリケーションフレームワーク Revel の公式チュートリアルをやってみた話でした。

Revel を使ったサンプルアプリケーションはいくつか公開されているので、次回は DB へのアクセスも含めたサンプルアプリケーションを触ってみようと思います。


comments powered by Disqus