## 7.7\. template包
template包是GO標準庫的一個部分。我們使用template將HTML存放在一個單獨的文件中,可以更改編輯頁面的布局而不用修改相關的GO代碼。
首先,我們必須將template添加到導入列表:
```
import (
"http"
"io/ioutil"
"os"
"template"
)
```
創建一個包含HTML表單的模板文件。打開一個名為edit.html的新文件,添加下面的行:
```
<h1>Editing {title}</h1>
<form action="/save/{title}" method="POST">
<div><textarea name="body" rows="20" cols="80">{body|html}</textarea></div>
<div><input type="submit" value="Save"></div>
</form>
```
修改editHandler,用模板替代硬編碼的HTML。
```
func editHandler(w http.ResponseWriter, r *http.Request) {
title := r.URL.Path[lenPath:]
p, err := loadPage(title)
if err != nil {
p = &page{title: title}
}
t, _ := template.ParseFile("edit.html", nil)
t.Execute(p, w)
}
```
函數template.ParseFile讀取edit.html的內容,返回*template.Template類型的數據。
方法t.Execute用p.title和p.body的值替換模板中所有的{title}和{body},并且把結果寫到http.Conn。
注意,在上面的模板中我們使用{body|html}。|html部分請求模板引擎在輸出body的值之前,先將它傳到html格式化器(formatter),轉義HTML字符(比如用&aamp;gt;替換>)。 這樣做,可以阻止用戶數據破壞表單HTML。
既然我們刪除了fmt.Sprintf語句,我們可以刪除導入列表中的"fmt"。
使用模板技術,我們可以為viewHandler創建一個模板,命名為view.html。
```
<h1>{title}</h1>
<p>[<a href="/edit/{title}">edit</a>]</p>
<div>{body}</div>
```
修改viewHandler:
```
func viewHandler(w http.ResponseWriter, r *http.Request) {
title := r.URL.Path[lenPath:]
p, _ := loadPage(title)
t, _ := template.ParseFile("view.html", nil)
t.Execute(p, w)
}
```
注意,在兩個處理函數(handler)中使用了幾乎完全相同的模板處理代碼,我們可以把模板處理代碼寫成一個單獨的函數,以消除重復。
```
func viewHandler(w http.ResponseWriter, r *http.Request) {
title := r.URL.Path[lenPath:]
p, _ := loadPage(title)
renderTemplate(w, "view", p)
}
func editHandler(w http.ResponseWriter, r *http.Request) {
title := r.URL.Path[lenPath:]
p, err := loadPage(title)
if err != nil {
p = &page{title: title}
}
renderTemplate(w, "edit", p)
}
func renderTemplate(w http.ResponseWriter, tmpl string, p *page) {
t, _ := template.ParseFile(tmpl+".html", nil)
t.Execute(p, w)
}
```
現在,處理函數(handler)代碼更短、更加簡單。
- 1. 關于本文
- 2. Go語言簡介
- 3. 安裝go環境
- 3.1. 簡介
- 3.2. 安裝C語言工具
- 3.3. 安裝Mercurial
- 3.4. 獲取代碼
- 3.5. 安裝Go
- 3.6. 編寫程序
- 3.7. 進一步學習
- 3.8. 更新go到新版本
- 3.9. 社區資源
- 3.10. 環境變量
- 4. Go語言入門
- 4.1. 簡介
- 4.2. Hello,世界
- 4.3. 分號(Semicolons)
- 4.4. 編譯
- 4.5. Echo
- 4.6. 類型簡介
- 4.7. 申請內存
- 4.8. 常量
- 4.9. I/O包
- 4.10. Rotting cats
- 4.11. Sorting
- 4.12. 打印輸出
- 4.13. 生成素數
- 4.14. Multiplexing
- 5. Effective Go
- 5.1. 簡介
- 5.2. 格式化
- 5.3. 注釋
- 5.4. 命名
- 5.5. 分號
- 5.6. 控制流
- 5.7. 函數
- 5.8. 數據
- 5.9. 初始化
- 5.10. 方法
- 5.11. 接口和其他類型
- 5.12. 內置
- 5.13. 并發
- 5.14. 錯誤處理
- 5.15. Web服務器
- 6. 如何編寫Go程序
- 6.1. 簡介
- 6.2. 社區資源
- 6.3. 新建一個包
- 6.4. 測試
- 6.5. 一個帶測試的演示包
- 7. Codelab: 編寫Web程序
- 7.1. 簡介
- 7.2. 開始
- 7.3. 數據結構
- 7.4. 使用http包
- 7.5. 基于http提供wiki頁面
- 7.6. 編輯頁面
- 7.7. template包
- 7.8. 處理不存在的頁面
- 7.9. 儲存頁面
- 7.10. 錯誤處理
- 7.11. 模板緩存
- 7.12. 驗證
- 7.13. 函數文本和閉包
- 7.14. 試試!
- 7.15. 其他任務
- 8. 針對C++程序員指南
- 8.1. 概念差異
- 8.2. 語法
- 8.3. 常量
- 8.4. Slices(切片)
- 8.5. 構造值對象
- 8.6. Interfaces(接口)
- 8.7. Goroutines
- 8.8. Channels(管道)
- 9. 內存模型
- 9.1. 簡介
- 9.2. Happens Before
- 9.3. 同步(Synchronization)
- 9.4. 錯誤的同步方式
- 10. 附錄
- 10.1. 命令行工具
- 10.2. 視頻和講座
- 10.3. Release History
- 10.4. Go Roadmap
- 10.5. 相關資源