เทมเพลต
เกี่ยวกับบทเรียน
แพ็กเกจ html/template
ที่มีมาให้เราได้ใช้เป็นเทมเพลตสำหรับภาษา HTML ที่เพรียบร้อม
สำหรับใช้ในส่วนของการแสดงผลข้อมูลสำหรับเว็บแอปพลิเคชั่นในเว็บเบราว์เซอร์ของผู้ใช้งาน
ข้อดีอย่างหนึ่งของ เทมเพลตในภาษา Go ก็เห็นจะเป็นเรื่องของการ escape ข้อมูลที่ได้รับมาโดยอัตโนมัติ
ดังนั้นเราก็หายห่วงในเรื่องการโจมตีแบบ XSS ไปได้เลย เพราะภาษา Go จะทำการวิเคราะห์ HTML เพมเพลต
และจะ escape อินพุตทั้งหมดที่รับมาก่อนที่จะทำการแสดงผลออกไปยังหน้าเบราว์เซอร์
เทมเพลตตัวแรก
การใช้งานหรือเขียนเทมเพลตในภาษา Go นั้นไม่มีอะไรซับซ้อนเลย จากตัวอย่างต่อไปนี้จะแสดงให้เห็นการส้าง TODO ลิส โดยทำการเขียนออกมาเป็น ul ในภาษา HTML
ในขณะที่ทำการประมวลผลเทมเพลตนั้น ข้อมูลที่ถูกส่งเข้ามาสามารถที่จะเป็นข้อมูลชนิดใดก็ได้ที่มาจากโครงสร้งข้อมูลของภาษา Go มันสามารถรับได้ทั้งแบบตัวอักษรและตัวเลข หรือว่าจะเป็นโครงสร้างข้อมูลแบบซ้อนทับกันเหมือนดังตัวอย่างด้านล่างนี้
การเข้าถึงข้อมูลชั้นแรกสุดที่ได้รับมาในเทมเพลตเราสามารถเข้าถึงได้โดย {{.}}
จุดข้างในวงเล็บปีกกา นั่นเรียกว่า ไปป์ไลน์ (pipeline) และเป็นองค์ประกอบรากของข้อมูลหรือข้อมูลลำดับแรก
data := TodoPageData{
PageTitle: "My TODO list",
Todos: []Todo{
{Title: "Task 1", Done: false},
{Title: "Task 2", Done: true},
{Title: "Task 3", Done: true},
},
}
<h1>{{.PageTitle}}<h1>
<ul>
{{range .Todos}}
{{if .Done}}
<li class="done">{{.Title}}</li>
{{else}}
<li>{{.Title}}</li>
{{end}}
{{end}}
</ul>
ไวยากรณ์ สำรหรับควบคุมการทำงาน (Control Structure)
เทมเพลตในภาษา GO ประกอบไปด้วยเซ็ทคำสั่งอันหลากหลายเพื่อควบคุมการทำงานต่างๆ สำหรับการประมวลผล HTML ของคุณ ตัวอย่างต่อไปนี้จะแสดงให้คุณเห็นถึงภาพรวมและคำสั้งต่างๆที่มีคนที่ใช้กันมากที่สุด หากต้องการทราบเพ่ิมเติมเกี่ยวกับรายชื่อคำสั่งต่างๆ ที่สามารถใช้งานได้ ขอให้เข้าไปที่ text/template
Control Structure | Definition |
---|---|
{{/* a comment */}} |
การเขียนคอมเมนต์ |
{{.}} |
แสดงข้อมูลทั้งหมด |
{{.Title}} |
แสดงข้อมูล “Title” จากข้อมูลที่ได้รับมา |
{{if .Done}} {{else}} {{end}} |
การเขียนคำสั่ง if |
{{range .Todos}} {{.}} {{end}} |
ลูป “Todos” และแสดงผลข้อมูลเมื่อทำการลูปด้วยไวยากรณ์ {{.}} |
{{block "content" .}} {{end}} |
กำหนดบล็อก (block) โดยใช้ชื่อว่า “content” |
ใช้เทมเพลตในรูปแบบของไฟล์แยก
เทมเพลตสามารที่จะใช้งานได้จากทั้ง การเขียนตรงๆหรือจากไฟล์ที่มีอยู่ในเครื่องของเรา
โดยปรกติแล้วเรามักที่จะใช้เทมเพลตโดยการสร้างไฟล์แยกและเก็บไว้ในเครื่องของเราเสียมากกว่า
ตัวอย่างด้านล่างจะแสดงให้เห็นวิธีการใช้งาน ตัวอย่างที่เห็นจะมีเทมเพลตในไดเรคทอรี่เดียวกันกับตัวไฟล์โปรแกรมของ Go ซึ่งถูกสร้างชึ้นมาในชื่อ layout.html
tmpl, err := template.ParseFiles("layout.html")
// or
tmpl := template.Must(template.ParseFiles("layout.html"))
ประมวลผมเทมเพลตใน Request Handler
เมื่อเรารับเทมเพลตมาจากไฟล์ที่ถูกสร้างขึ้นมาเรียบร้อยแล้ว เราก็สามารถนำมันมาใช้ใน request handler ได้เลย
ฟังก์ชัน Execute
รับค่า io.Writer
เพื่อใช้เขียนข้อมูลในเทมเพลตและ interface{}
เพื่อส่งข้อมูลกลับไปให้เทมเพลตอีกทีหนึ่ง
เมื่อฟังก์ชันที่การเรียก http.ResponseWriter
จากนั้น Content-Type ใน header จะถูกจัดการและเขียนข้อมูลโดยอัตโนมัติและส่งกลับมาเป็น Content-Type: text/html; charset=utf-8
func(w http.ResponseWriter, r *http.Request) {
tmpl.Execute(w, "data goes here")
}
โค้ด (สำหรับทดสอบ copy/paste)
นี่เป็นตัวโค้ดที่เสร็จสมบูรณ์ ซึ่งคุณสามารถนำไปใช้ทดสอบได้ เป็นโค้ดที่คุณได้เรียนรู้มาทั้งหมดในบทเรียนบทนี้
package main
import (
"html/template"
"net/http"
)
type Todo struct {
Title string
Done bool
}
type TodoPageData struct {
PageTitle string
Todos []Todo
}
func main() {
tmpl := template.Must(template.ParseFiles("layout.html"))
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
data := TodoPageData{
PageTitle: "My TODO list",
Todos: []Todo{
{Title: "Task 1", Done: false},
{Title: "Task 2", Done: true},
{Title: "Task 3", Done: true},
},
}
tmpl.Execute(w, data)
})
http.ListenAndServe(":80", nil)
}
<h1>{{.PageTitle}}<h1>
<ul>
{{range .Todos}}
{{if .Done}}
<li class="done">{{.Title}}</li>
{{else}}
<li>{{.Title}}</li>
{{end}}
{{end}}
</ul>