演習a4
text/templateパッケージについて,極々単純なWebアプリケーションで演習します.
演習(補足:templateパッケージ)
演習(補足:templateパッケージ)
(1)
- Webブラウザからアクセスすると,名前を入力するフォームを表示し,フォームに名前を入力してSayHelloボタンをクリックすると,"Hello, ○○"と表示するhttpサーバ(Webサーバ)を作成せよ.このサービスのポートは123456とする.
(2)
- Webブラウザからアクセスすると,名前と言語を入力するフォームを表示し,フォームに入力して,SayHelloボタンをクリックすると,指定された言語であいさつするhttpサーバ(Webサーバ)を作成せよ.
- 言語は,英語,日本語,中国語,韓国語,エスペラント語とし,それぞれ,"Hello,○○","こんにちは,○○","你好 ○○","안녕하세요?○○","Bonan tagon,○○"と表示するものとする.(○○は入力した名前)
解答例(1)
解答例(1)
ソースファイル (a4-1-template.go)
- package main
- import (
- "text/template"
- "net/http"
- "fmt"
- "log"
- )
- func helloHandler(w http.ResponseWriter, r *http.Request) {
- fmt.Println("hello")
- w.Header().Set("Content-Type", "text/html") // content-typeの指定
- t := template.Must(template.ParseFiles("hello1.html"))
- err := t.Execute(w, r.FormValue("who"))
- if err != nil {
- fmt.Println(err.Error())
- }
- }
- func main() {
- http.HandleFunc("/", helloHandler)
- log.Fatal(http.ListenAndServe(":10080",nil))
- }
HTMLテンプレート (hello1.html)
- <!DOCTYPE htm>
- <head>
- <meta charset="utf-8" />
- <title>Hello!</title>
- </head>
- <body>
- <form action="/" method="POST">
- 誰に?
- <input type="text" name="who" />
- <input type="submit" value="Say Hello" />
- </form>
- {{if .}}
- Hello, {{.|html}}!
- {{end}}
- </body>
- </html>
解説(1)
解説(1)
- templateパッケージは,HTMLなどのテキスト出力を生成するためのデータ駆動型テンプレートです.
- テンプレートは,HTMLファイルの可変部分を"{{"と"}}"でくくったもの(アクションと呼ぶ)で記述します.テンプレートファイルの文字コードはUTF-8です.
- テンプレートの実行時に,アクション部分が,参照しているプログラム中のデータの値に応じて書き換えられ,その結果がブラウザに返されます.
- テンプレートからプログラム中のデータにアクセスするには,プログラム側のExecuteメソッドでデータを指定し(ソースの13行目),テンプレート側で,アーギュメントを用いてそのデータを参照します(テンプレートの13行目から15行目がアクション,"."がアーギュメント).この例では,POSTメソッドで送られたwhoの値が,"."の値になります.
- テンプレート13行目の"{{if .}}"は,アーギュメントに値がセットされていれば("who"になにか入力されてからPOSTされたのなら)14行目を実行する,ということを表しています.
- 14行目の{{.|html}}は,アーギュメント"."の値をHTMLエスケープします.例えば,"."の値に>や<が含まれていたら,>や<に変換します.
- データには,マップや構造体を渡すこともできます.
- テンプレートの詳細は,言語仕様(英語)を参照してください.
マップで渡す
マップで渡す
- マップのキーをWhoとすると,その値は".Who"で参照できる.
- ソースの13行目
- t.Execute(w, map[string] string{"Who": r.FormValue("who")})
- テンプレートの13行目から15行目
- {{if .Who}}
- Hello, {{.Who|html}}!
- {{end}}
構造体で渡す
構造体で渡す
- 構造体名をData,フィールド名をWhoとすると,その値は,".Who"で参照できる.構造体のフィールド名は他のパッケージから参照できるように大文字でなければならない
- Dataの宣言
- type Data struct {Who string}
- ソースの13行目
- t.Execute(w, Data{r.FormValue("who")})
- テンプレートの13行目から15行目
- {{if .Who}}
- Hello, {{.Who|html}}!
- {{end}}
解答例(2)
解答例(2)
ソースコード
- package main
- import (
- "text/template"
- "net/http"
- "fmt"
- "log"
- )
- func handler(w http.ResponseWriter, r *http.Request) {
- fmt.Println("hello")
- w.Header().Set("Content-Type", "text/html") //***
- t := template.Must(template.ParseFiles("hello2.html"))
- err := t.Execute(w, map[string] string{"Hello": r.FormValue("lang"), "Who": r.FormValue("who")})
- if err != nil {
- fmt.Println(err.Error())
- }
- }
- func main() {
- http.HandleFunc("/", handler)
- log.Fatal(http.ListenAndServe(":10080",nil))
- }
HTMLテンプレート
- <!DOCTYPE htm>
- <head>
- <meta charset="utf-8" />
- <title>Hello!</title>
- </head>
- <body>
- <form action="/" method="POST">
- <p>誰に? <input type="text" name="who" /></p>
- <p>言語は?
- <select name="lang" size="1">
- <option value="Hello,">English</option>
- <option value="こんにちは,">Jananese</option>
- <option value="你好 ">Chinese</option>
- <option value="안녕하세요?">Korean</option>
- <option value="Bonan tagon,">Esperanto</option>
- </select>
- </p>
- <input type="submit" value="Say Hello" />
- </form>
- {{if .Who}}
- <p>{{.Hello}} {{.Who|html}}!</p>
- {{end}}
- </body>
- </html>
解説(2)
解説(2)
- 二つの値を渡すので,HelloとWhoをキーとするマップを使っています(ソースの12行目).HTMLテンプレートからそれらの値にアクセスするには,.Helloと.Whoを用います(テンプレートの21行目,22行目).