Go 模板嵌套最佳實務

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

Go 官方庫提供了兩個模板庫: text/template 和 html/template 。這兩個庫類似,只不過 html/template 對html格式做了特別的處理,當需要輸出html格式的代碼時需要使用 html/template 。

使用模版,可以協助我們寫一些通用的代碼,或者提供清晰的檔案布局, 或者提供一個代碼產生器。

官方文檔提供了很好的模版的使用方法, 其中 text/template 提供了基礎的模版的使用方法,比如 Action、 Argument、Pipeline、Variable、Function、模版嵌套的介紹, html/template 對 Context 進行了介紹。 本文假定你已經瞭解了這些基礎知識。如果你還不清楚,或者還沒有用過模版,可以參考文末的參考文檔進行學習。

雖然 text/template 官方文檔對模版嵌套簡單了介紹,但是對於如何使用嵌套模版進行實際開發,以及注意事項並沒有詳細的介紹,所以本文著重介紹嵌套模版的使用。

雖然本文名稱為嵌套模版的最佳實務,但是準確的講,這隻是最佳實務之一。如果讀者有其它的實踐方案,或者更好的處理模版嵌套的方案,歡迎討論。

在我們開發web應用程式的時候,不可避免的要使用到模版。

一般一個網站包含很多的頁面,比如新聞頁面、註冊頁面、文章列表等。 不同的新聞可能使用同一個新聞布局模版,不同的文章詳細頁也可能使用同一個文章布局頁面, 同時新聞布局模版和文章布局頁面也可能有一些公用的東西,比如header、footer、導覽列等。如何將這些公用的東西抽取成統一的模版呢?

本文將逐步介紹這些技術, 首先介紹嵌套檔案的使用。

Parse vs ParseFiles vs ParseBlob

首先我們看一下這三個檔案有何不同。 事實上是五個檔案:

funcParseFiles(filenames ...string) (*Template, error)funcParseGlob(patternstring) (*Template, error)func(t *Template) Parse(textstring) (*Template, error)func(t *Template) ParseFiles(filenames ...string) (*Template, error)func(t *Template) ParseGlob(patternstring) (*Template, error)

Parse 用來解析一個字串,字串代表模版的內容,並且嵌套的模版也會和這個模版進行關聯。

tmpl, err := template.New("name").Parse(...)// Error checking elidederr = tmpl.Execute(out, data)

import"html/template"...t, err := template.New("foo").Parse(`\{\{define "T"\}\}Hello, \{\{.\}\}!\{\{end\}\}`)err = t.ExecuteTemplate(out, "T","<script>alert('you have been pwned')</script>")

ParseFiles 用來解析一組命名的檔案模版,當模版定義在不同的檔案中的時候,使用這個方法可以產生一個可執行檔模版,模版執行的時候不會出錯。

ParseGlob 與 ParseFiles 類似,它使用 filepath.Glob 模式比對的方式遍曆檔案,將這些檔案產生模版。

這兩個函數還可以作為 *Template 的方法使用。作為函數使用的時候,它返回模版的名字是第一個檔案的名字,模版以第一個檔案作為base模版。

同時後面的檔案也會產生模版作為這個模版的關聯模板,你可以通過 Lookup 方法尋找到這個模版,因為每個模版都儲存著它的關聯模版:

set map[string]*Template

我們以一個例子示範一下嵌套模版的使用。

當前檔案夾下有兩個檔案。

header.html

Title is \{\{.Title\}\}\{\{template "footer"\}\}

footer.html

\{\{define "footer"\}\}Body is \{\{.Body\}\}\{\{end\}\}

測試程式:

packagemainimport("fmt""html/template""net/http")funchandler(w http.ResponseWriter, r *http.Request) { t, _ := template.ParseFiles("header.html","footer.html") err := t.Execute(w, map[string]string{"Title":"My title","Body":"Hi this is my body"})iferr !=nil{panic(err) }}funcmain() { http.HandleFunc("/", handler) http.ListenAndServe(":8080",nil)}

瀏覽器訪問 http://localhost:8080/ 會得到渲染的結果:

Title is My titleBody is

可以看到結果基本符合預期。 header.html 嵌套了 footer 模版,渲染的時候以 header.html 為主模版顯示,嵌套渲染了 footer.html 。

但是上面的結果顯示有一點點問題,就是 footer 渲染的時候並沒有顯示body的結果,這是因為data傳給了主模版,嵌套模版如果要使用這個資料,需要在嵌套的地方把data傳遞給它。我們可以修改 header.html :

Title is \{\{.Title\}\}\{\{template "footer" <div class=""></div>\}\}

這樣 footer.html 就可以使用傳入的data渲染了:

Title isMy titleBody isHithisismybody

在使用 ParseFiles 、 ParseGlob 函數 的時候,預設以檔案的路徑的最後一個部分作為模版名稱, 比如檔案 a/foo 的模版名稱為 foo ,但是如果參數中不同的檔案夾下有相同的檔案名稱時,最後那個同名的模版檔案會"覆蓋"前面的重名檔案模版,官方庫的實現中不能儲存重名的模版檔案。

Execute vs ExecuteTemplate

上面的例子顯示了一個簡單的嵌套模版的使用,但是如果我們把兩個檔案的順序交換一下,如下所示:

funchandler(w http.ResponseWriter, r *http.Request) { t, _ := template.ParseFiles("footer.html","header.html") err := t.Execute(w, map[string]string{"Title":"My title","Body":"Hi this is my body"})iferr !=nil{panic(err) }}

運行後瀏覽器訪問一下,會發現沒報錯,但是也沒有渲染任何東西。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.