Go Web 編程入門:Go 模板
之前的文章學過把模板和視圖分離,建立一個 Web 服務器來展現 HTML 模板。我們將學習如何使用 Go 的模板包創建動態 HTML 和文本文件。
建立 Web 服務器
到目前為止,我們一直在向終端輸出模板,但是當我們開始深入研究更多 HTML 時,這開始變得不那么有意義了。相反,我們希望可視化在 Web 瀏覽器中生成的 HTML。為此,我們首先需要設置一個 Web 服務器來呈現我們的 HTML 模板。
package main import ( "html/template" "net/http" ) var testTemplate *template.Template type ViewData struct { Name string } func main() { var err error testTemplate, err = template.ParseFiles("hello.gohtml") if err != nil { panic(err) } http.HandleFunc("/", handler) http.ListenAndServe(":8000", nil) } func handler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") vd := ViewData{"Kyrie Jobs"} err := testTemplate.Execute(w, vd) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) } }
創建一個名為 hello.gohtml 的文件并將以下內容添加到其中:
Hello, {{.Name}}!
現在通過在終端中輸入 go run main.go 來啟動服務器。該程序應保持運行并在端口 8000 上偵聽 Web 請求,因此您可以在 localhost:8000 查看呈現的 HTML。
if...else 塊
我們當前的模板很無聊,因為它只打印出一個人的名字。但是如果沒有提供名字會發生什么?
讓我們試試看。打開你的 main.go 文件并刪除你的 handler() 函數中創建 ViewData 實例的代碼,而是向 testTemplate.Execute 方法提供 nil 。完成后,您的 handler() 函數應如下所示:
func handler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") err := testTemplate.Execute(w, nil) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) } }
現在重新啟動您的服務器(或讓新服務器重新啟動)并在瀏覽器中訪問該頁面 - localhost:8000。您應該看到一個看起來像這樣的頁面。
當我們不提供名稱時,模板將使用空字符串代替值呈現。相反,我們希望我們的頁面顯示一個更通用的字符串,例如“Hello, there!”。讓我們繼續更新模板以使用我們的第一個操作,即 if/else 塊。像這樣更新 hello.gohtml:
Hello, {{if .Name}} {{.Name}} {{else}} there {{end}}!
如果您在瀏覽器中查看該頁面,您應該會看到這更新了您的模板以顯示“Hello, there !”就像我們想要的那樣,但不幸的是,這在“there”這個詞和感嘆號之間增加了一個額外的空格。大多數時候這并不重要,但是在處理文本時,這有時會很煩人。在下一節中,我們將看看兩個選項來稍微清理一下。
為了擺脫額外的空白,我們有幾個選擇:
從我們的模板中刪除它們。
使用減號 (-) 告訴模板包修剪多余的空白。
第一個選項非常簡單。我們只需將 hello.gohtml 文件更新為并刪除多余的空格。
Hello, {{if .Name}}{{.Name}}{{else}}there{{end}}!
在這個例子中,這很好用,因為它是一段非常短的文本,但是想象一下我們正在生成 python 代碼,其中間距很重要 - 這很快就會變得非常煩人。幸運的是,模板包還提供了一種使用減號來修剪不需要的空白的方法。
Hello, {{if .Name}} {{.Name}} {{- else}} there {{- end}}!
在此代碼片段中,我們通過將減號字符放在 else 關鍵字的前面來告訴模板包,我們不希望 Name 變量及其后面的任何內容之間的所有空格,并且我們也對 end 執行相同操作倒數第二行的關鍵字。重新加載您的頁面,您應該會看到該空格不再存在。
對于本教程的其余部分,我將選擇使用此處的第一個示例作為我的 hello.html 文件。
范圍塊
現在讓我們假設您想在您的網站上顯示所有小部件以及它們的價格。這是動態 Web 應用程序的任務類型,因為沒有人愿意為您銷售的每件商品手動創建 HTML 并維護它。相反,我們希望對每個項目使用相同的 HTML。在 Go 中,您可以使用模板內的范圍塊來實現此目的。
{{range .Widgets}}
{{end}}如果你重啟你的服務器(或者讓新的)并在 localhost:8000 重新加載頁面,你現在應該會看到一個 HTML 頁面,其中顯示了三個小部件,每個小部件都有一個標題和一個價格。如果我們在數組中添加更多小部件,我們會在這里看到更多,如果我們將其保留為空數組,我們將不會在此處看到任何小部件。
與 range 操作混淆的最常見來源是我們正在訪問小部件的各個屬性,而無需在 .Widgets 值內使用索引或任何其他訪問器。這是因為范圍操作會將集合中每個對象的值設置為范圍塊內的點 (.)。例如,如果您要在范圍塊內渲染 {{.}},您將看到與在 Widget 對象上使用 fmt.Println() 相同的輸出。
嵌套模板
隨著您的模板開始增長,您會很快發現您需要在不同的地方重用組件。這就是嵌套模板來拯救這一天的地方。使用 Go 的模板包,您可以聲明多個唯一命名的模板,然后當您需要在代碼中使用另一個模板時,您只需使用 template 關鍵字引用它。例如,假設您想為您的網站聲明一個頁腳,您可以將其包含在多個頁面和多個布局中。將以下頁腳模板添加到 hello.html 文件中。你把它放在哪里并不重要,但我更喜歡把它放在文件的頂部。
{{define "footer"}} {{end}}
然后在小部件的范圍塊之后插入以下行。
{{template "footer"}}
您的 hello.gohtml 文件應如下所示:
{{define "footer"}} {{end}} {{range .Widgets}}
{{end}} {{template "footer"}}現在,如果您查看 localhost:8000,您將看到該頁面正在使用您定義的頁腳模板。當您定義一個模板時,您可以在任何其他模板中使用它,甚至可以多次使用它。嘗試包含頁腳模板兩次以了解我的意思。
模板變量
我們的上一個示例很棒,但是當您需要在嵌套模板中包含一些數據時會發生什么?幸運的是,模板操作允許您傳入第二個參數,該參數將分配給模板內的點 (.) 參數。例如,假設我們想為小部件的名稱標題部分編寫模板,我們可以使用以下代碼來實現。
{{define "widget-header"}}
{{.}}
{{end}} {{range .Widgets}} {{end}}在這種情況下,.Name 屬性被分配給 widget-header 模板內的點 (.) 屬性。
帶有模板變量的嵌套模板甚至允許您深入多層,這意味著可以從模板內部調用模板。
{{define "widget"}}
{{end}} {{define "widget-header"}}{{.}}
{{end}} {{range .Widgets}} {{template "widget" .}} {{end}}這段代碼的最終結果是相同的,但是現在我們有了一個小部件模板,我們可以輕松地在 Web 應用程序的其他頁面上重用它,而無需重寫代碼。
接下來
憑借您新學到的模板技能,您應該可以創建可重用的動態模板。在下一篇文章中,我們將介紹如何使用內置的模板函數,如 and、eq、index,然后我們將看看如何添加我們自己的自定義函數。我原本打算包括那些聽到的,但這篇文章有很多要介紹的行動,我不想賣空任何一個。
在關于函數的帖子之后,我們將介紹如何使用模板來創建 Web 應用程序的視圖層。這將包括創建共享布局、定義可以被覆蓋的默認模板,以及在不同頁面中包含相同的模板,而無需將所有代碼放入單個文件中。
如果您感到雄心勃勃或好奇,您還可以查看 text/template 和 html/template 的模板文檔。繼續自己探索其他一些知識~
Go web前端
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。