勉強部屋‎ > ‎Go 1‎ > ‎

演習a4

text/templateパッケージについて,極々単純なWebアプリケーションで演習します.

演習(補足:templateパッケージ)

(1)
  • Webブラウザからアクセスすると,名前を入力するフォームを表示し,フォームに名前を入力してSayHelloボタンをクリックすると,"Hello, ○○"と表示するhttpサーバ(Webサーバ)を作成せよ.このサービスのポートは123456とする.
(2)
  • Webブラウザからアクセスすると,名前と言語を入力するフォームを表示し,フォームに入力して,SayHelloボタンをクリックすると,指定された言語であいさつするhttpサーバ(Webサーバ)を作成せよ.
  • 言語は,英語,日本語,中国語,韓国語,エスペラント語とし,それぞれ,"Hello,○○","こんにちは,○○","你好 ○○","안녕하세요?○○","Bonan tagon,○○"と表示するものとする.(○○は入力した名前)

解答例(1)

ソースファイル (a4-1-template.go)
  1. package main
  2. import (
  3.     "text/template"
  4.     "net/http"
  5.     "fmt"
  6.     "log"
  7. )

  8. func helloHandler(w http.ResponseWriter, r *http.Request) {
  9.     fmt.Println("hello")
  10.     w.Header().Set("Content-Type", "text/html") // content-typeの指定
  11.     t := template.Must(template.ParseFiles("hello1.html"))
  12.     err := t.Execute(w, r.FormValue("who"))
  13.     if err != nil {
  14.         fmt.Println(err.Error())
  15.     }
  16. }

  17. func main() {
  18.     http.HandleFunc("/", helloHandler)
  19.     log.Fatal(http.ListenAndServe(":10080",nil))
  20. }
HTMLテンプレート (hello1.html)
  1. <!DOCTYPE htm>
  2. <head>
  3. <meta charset="utf-8" />
  4. <title>Hello!</title>
  5. </head>
  6. <body>
  7. <form action="/" method="POST">
  8.     誰に?
  9.     <input type="text" name="who" />
  10.     <input type="submit" value="Say Hello" />
  11. </form>
  12.  
  13. {{if .}} 
  14. Hello, {{.|html}}!
  15. {{end}}
  16. </body>
  17. </html>

解説(1)

  • templateパッケージは,HTMLなどのテキスト出力を生成するためのデータ駆動型テンプレートです.
  • テンプレートは,HTMLファイルの可変部分を"{{"と"}}"でくくったもの(アクションと呼ぶ)で記述します.テンプレートファイルの文字コードはUTF-8です.
  • テンプレートの実行時に,アクション部分が,参照しているプログラム中のデータの値に応じて書き換えられ,その結果がブラウザに返されます.
  • テンプレートからプログラム中のデータにアクセスするには,プログラム側のExecuteメソッドでデータを指定し(ソースの13行目),テンプレート側で,アーギュメントを用いてそのデータを参照します(テンプレートの13行目から15行目がアクション,"."がアーギュメント).この例では,POSTメソッドで送られたwhoの値が,"."の値になります.
  • テンプレート13行目の"{{if .}}"は,アーギュメントに値がセットされていれば("who"になにか入力されてからPOSTされたのなら)14行目を実行する,ということを表しています.
  • 14行目の{{.|html}}は,アーギュメント"."の値をHTMLエスケープします.例えば,"."の値に>や<が含まれていたら,&gt;や&lt;に変換します.
  • データには,マップや構造体を渡すこともできます.
  • テンプレートの詳細は,言語仕様(英語)を参照してください.

マップで渡す

  • マップのキーを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)

ソースコード
  1. package main
  2. import (
  3.     "text/template"
  4.     "net/http"
  5.     "fmt"
  6.     "log"
  7. )
  8. func handler(w http.ResponseWriter, r *http.Request) {
  9.     fmt.Println("hello")
  10.     w.Header().Set("Content-Type", "text/html")  //***
  11.     t := template.Must(template.ParseFiles("hello2.html"))
  12.     err := t.Execute(w, map[string] string{"Hello": r.FormValue("lang"), "Who": r.FormValue("who")})
  13.     if err != nil {
  14.         fmt.Println(err.Error())
  15.     }
  16. }
  17. func main() {
  18.     http.HandleFunc("/", handler)
  19.     log.Fatal(http.ListenAndServe(":10080",nil))
  20. }
HTMLテンプレート
  1. <!DOCTYPE htm>
  2. <head>
  3. <meta charset="utf-8" />
  4. <title>Hello!</title>
  5. </head>
  6. <body>
  7. <form action="/" method="POST">
  8.     <p>誰に? <input type="text" name="who" /></p>
  9.     <p>言語は?
  10.     <select name="lang" size="1">
  11.         <option value="Hello,">English</option>
  12.         <option value="こんにちは,">Jananese</option>
  13.         <option value="你好 ">Chinese</option>
  14.         <option value="안녕하세요?">Korean</option>
  15.         <option value="Bonan tagon,">Esperanto</option>
  16.     </select>
  17.     </p>
  18.     <input type="submit" value="Say Hello" />
  19. </form>
  20.  
  21. {{if .Who}} 
  22.     <p>{{.Hello}} {{.Who|html}}!</p>
  23. {{end}}
  24. </body>
  25. </html>

解説(2)

  • 二つの値を渡すので,HelloとWhoをキーとするマップを使っています(ソースの12行目).HTMLテンプレートからそれらの値にアクセスするには,.Helloと.Whoを用います(テンプレートの21行目,22行目).
ċ
a4-1-template.go
(0k)
Tetsuo Tanaka,
2012/04/29 20:41
ċ
a4-2-template.go
(1k)
Tetsuo Tanaka,
2012/04/29 20:42
ċ
hello1.html
(0k)
Tetsuo Tanaka,
2012/04/30 2:52
ċ
hello2.html
(1k)
Tetsuo Tanaka,
2012/04/30 2:52
Comments