【Go実践】POSTされたデータを受け取って処理する ― 入力フォームと確認画面の作成

シェアする

前回の記事で、HTMLテンプレートの利用方法を解説しました。
【Go実践】html/templateパッケージ ‐ GoのHTMLテンプレート機能を利用する

テンプレートの利用によって、HTMLデザインとビジネスロジックを分離することができます。
今後はこの機能を利用して、GoによるWEB開発の手法を解説していきます。

今回は、入力フォームからPOSTされた値を受け取って画面に出力するプログラムを解説します。
題材として、こちらの記事で作成したユーザマスタ情報の登録フォームを作成してみることにしましょう。

入力フォームの作成

入力フォームのテンプレート

まずは入力フォーム画面のデザインテンプレートを作成します。
templatesディレクトリuser-form.gtplファイルを作成し、以下のように記述してください。

<!DOCTYPE html>
<html>
<body>
  <h2>新規ユーザの登録</h2>
  <form action="user-confirm" method="post">
    <table>
      <tr>
        <td>アカウント名</td>
        <td><input type="text" name="account"></td>
      </tr>
      <tr>
        <td>お名前</td>
        <td><input type="text" name="name"></td>
      </tr>
      <tr>
          <td>パスワード</td>
          <td><input type="password" name="passwd"></td>
        </tr>
    </table>
    <input type="submit" value="確認画面へ">
  </form>
</body>
</html>

必要項目を入力して送信するだけの、シンプルな入力フォームです。
入力項目はとりあえず、アカウント名・ユーザ名・パスワードの3項目です。
ボタンクリック時時のsubmit先はuser-confirmとしています。

入力フォームを出力するプログラム

確認画面を作成する前に、ひとまずここで入力フォームを表示するプログラムを作成し、意図通りに表示できるか確認してみましょう。

package main

import (
    "fmt"
    "html/template"
    "net/http"
)

// 入力フォーム画面
func HandlerUserForm(w http.ResponseWriter, r *http.Request) {
    // テンプレートをパースする
    tpl := template.Must(template.ParseFiles("templates/user-form.gtpl"))

    // テンプレートに出力する値をマップにセット
    values := map[string]string{}

    // マップを展開してテンプレートを出力する
    if err := tpl.ExecuteTemplate(w, "user-form.gtpl", values); err != nil {
        fmt.Println(err)
    }
}

func main() {

    // "user-form"へのリクエストを関数で処理する
    http.HandleFunc("/user-form", HandlerUserForm)

    // サーバーを起動
    http.ListenAndServe(":8080", nil)
}

テンプレートに流入すべき変数値がありませんので、15行目のマップに項目は必要ありません。
入力フォーム画面のパスは、/user-formとしています。

それではこのコードを実行し、ブラウザでhttp://localhost:8080/user-formにアクセスしてみてください。
以下のように出力されれば想定通りです。

POST値を受け取る確認画面の作成

続いて、入力フォームからPOSTで受け取った入力値を表示する確認画面を作成していきます。

確認画面のテンプレート

確認画面のテンプレートですが、前回作成したsample.gtplを流用しましょう。
sample.gtplをコピーしてuser-confirm.gtplとリネームしたら、以下のように記述してください。

<!DOCTYPE html>
<html>
<body>
  <h2>登録内容の確認</h2>
  <table>
    <tr>
      <td>アカウント名:</td>
      <td>{{.account}}</td>
    </tr>
    <tr>
      <td>お名前:</td>
      <td>{{.name}}</td>
    </tr>
    <tr>
      <td>パスワード:</td>
      <td>{{.passwd}}</td>
    </tr>
  </table>
  <button type="button" onclick="history.back()">入力画面に戻る</button>
</body>
</html>

タイトルと[戻る]ボタンを追加した以外は変更はありません。
既に入力値に対応するの可変フィールドは作成済ですので、ここにPOST値をそれぞれ流入することになります。

確認画面を出力するプログラム

それではいよいよ、POST値の処理を行うプログラムを記述します
GoプログラムでHTTPリクエストのPOST値を受け取るには、net/httpパッケージのRequest.FormValue関数またはRequest.PostFormValue関数を使用します。

func (r *Request) FormValue([キー名] string) string
func (r *Request) PostFormValue([POSTデータのキー名] string) string

FormValueは、クエリの名前付きコンポーネントの最初の値を返します。
PostFormValueは、POSTリクエストの名前付きコンポーネントの最初の値を返します。

端的に言えば、FormValueはPOSTだけでなくURLクエリパラメータも同時に処理することができるのに対し、PostFormValueはPOSTリクエストボディだけを扱います。

基本的にはFormValueを使用すれば問題ないと思いますが、意図的にクエリパラメータを除外したい場合はPostFormValueを使用すると良いでしょう。

それでは、main.goに確認画面の出力処理を追記します。

package main

import (
    "fmt"
    "html/template"
    "net/http"
)

// 入力フォーム画面
func HandlerUserForm(w http.ResponseWriter, r *http.Request) {
    // テンプレートをパースする
    tpl := template.Must(template.ParseFiles("templates/user-form.gtpl"))

    // テンプレートに出力する値をマップにセット
    values := map[string]string{}

    // マップを展開してテンプレートを出力する
    if err := tpl.ExecuteTemplate(w, "user-form.gtpl", values); err != nil {
        fmt.Println(err)
    }
}

// 入力内容の確認画面
func HandlerUserConfirm(w http.ResponseWriter, req *http.Request) {
    // テンプレートをパースする
    tpl := template.Must(template.ParseFiles("templates/user-confirm.gtpl"))

    // テンプレートに出力する値をマップにセット
    values := map[string]string{
        "account": req.FormValue("account"),
        "name":    req.FormValue("name"),
        "passwd":  req.FormValue("passwd"),
    }

    // マップを展開してテンプレートを出力する
    if err := tpl.ExecuteTemplate(w, "user-confirm.gtpl", values); err != nil {
        fmt.Println(err)
    }
}

func main() {

    // "user-form"へのリクエストを関数で処理する
    http.HandleFunc("/user-form", HandlerUserForm)

    // "user-confirm"へのリクエストを関数で処理する
    http.HandleFunc("/user-confirm", HandlerUserConfirm)

    // サーバーを起動
    http.ListenAndServe(":8080", nil)
}

まずは47行目に着目してください。
フォーム画面からPOSTリクエストを送信する際のsubmit先がuser-confirmですので、user-confirmへのリクエストハンドラを定義しています。

このハンドラとなるHandlerUserConfirm関数内で、POSTデータの処理を行います。
テンプレートに流入するデータのmapに、req.FormValueで対応するフォームの入力値をセットしています。

実行結果

それではこのコードを実行し、ブラウザでhttp://localhost:8080/user-formにアクセスしてみてください。

フォームに入力を行い、[確認画面へ]をクリックします。

以下のように、フォームへ入力した値が確認画面に出力されれば想定通りです。

終わりに

今回は、POSTによる画面間のデータ受け渡し方法をサンプルとともに解説しました。
シンプルな実装ですが、この手法で基本的なWEBフォームは開発できるかと思います。

次回の記事では、ここまでに解説した技術を総合し、フォームへの入力値をデータベースへ登録するサンプルを紹介します。

スポンサーリンク
スポンサーリンク
スポンサーリンク

シェアする

フォローする

スポンサーリンク
スポンサーリンク