通過以下文章,掌握了 Go 模板引擎 的基本用法:
但在開始學習 Beego 框架的 模板嵌套 模塊源碼時,有點似懂非懂的感覺。認真研究了一段時間,總算搞懂了 其本質的原理:
1、Beego 底層用的是 Go 自帶的模板引擎,因此,只需要繼續研究 Go 自帶的 模板嵌套 的使用方法即可;
2、主要涉及到 4 個模板方法:New()、Parse()、Lookup()、Execute(),先看幾個例子:
示例1:
tpl, _ := template.New("mod1").Parse(`我是mod1`) tpl, _ = tpl.New("mod2").Parse(`我是mod2`) tpl, _ = tpl.New("mod3").Parse(`我是mod3`) tpl.Execute(os.Stdout, nil) fmt.Println("\n++++++++++++++++") fmt.Println(tpl.Name())
輸出:
我是mod3 ++++++++++++++++ mod3
示例2:
tpl, _ := template.New("mod1").Parse(`我是mod1`) tpl, _ = tpl.New("mod2").Parse(`我是mod2`) tpl, _ = tpl.New("mod3").Parse(`我是mod3`) tpl2 := tpl.Lookup("mod2") if tpl2 != nil { tpl2.Execute(os.Stdout, nil) }
輸出:
我是mod2
示例3:
tpl, _ := template.New("mod1").Parse(`我是mod1`) tpl, _ = tpl.New("mod2").Parse(`{{define "Title"}}我是mod2_標題{{end}}我是mod2_內容`) tpl, _ = tpl.New("mod3").Parse(`我是mod3`) tpl2 := tpl.Lookup("mod2") if tpl2 != nil { tpl2.Execute(os.Stdout, nil) }
輸出:
我是mod2_內容
示例4:
tpl, _ := template.New("mod1").Parse(`我是mod1`) tpl, _ = tpl.New("mod2").Parse(`{{define "Title"}}我是mod2_標題{{end}}我是mod2_內容`) tpl, _ = tpl.New("mod3").Parse(`我是mod3`) tpl2 := tpl.Lookup("Title") if tpl2 != nil { tpl2.Execute(os.Stdout, nil) }
輸出:
我是mod2_標題
示例5:
tpl, _ := template.New("mod1").Parse(`我是mod1`) tpl, _ = tpl.New("mod2").Parse(`{{define "Title"}}我是mod2_標題{{end}}我是mod2_內容`) tpl, _ = tpl.New("mod3").Parse(`我是mod3`) tpl = tpl.New("mod4") tpl, _ = tpl.New("mod5").Parse("我是mod5") fmt.Println(tpl.Name()) fmt.Println("+++++++++++++++") tpl2 := tpl.Lookup("mod4") if tpl2 != nil { tpl2.Execute(os.Stdout, nil) } tpl3 := tpl.Lookup("mod5") if tpl3 != nil { tpl3.Execute(os.Stdout, nil) }
輸出:
mod5 +++++++++++++++ 我是mod5
示例6:
tpl, _ := template.New("mod1").Parse(`我是mod1`) tpl, _ = tpl.New("mod2").Parse(`{{define "Title"}}我是mod2_標題{{end}}我是mod2_內容`) tpl, _ = tpl.New("mod1").Parse(`我是mod1_內容{{define "Title"}}我是mod1_標題{{end}}`) fmt.Println(tpl.Name()) fmt.Println("+++++++++++++++") tpl2 := tpl.Lookup("mod1") if tpl2 != nil { tpl2.Execute(os.Stdout, nil) } fmt.Println("\n+++++++++++++++") tpl3 := tpl.Lookup("Title") if tpl3 != nil { tpl3.Execute(os.Stdout, nil) }
輸出:
mod1 +++++++++++++++ 我是mod1_內容 +++++++++++++++ 我是mod1_標題
示例7:
tpl, _ := template.New("mod1").Parse(`我是mod1`) tpl, _ = tpl.New("mod2").Parse(`{{define "Title"}}我是mod2_標題{{end}}我是mod2_內容`) tpl, _ = tpl.New("mod3").Parse(`我是mod3_{{template "mod1"}}_{{template "Title"}}`) tpl2 := tpl.Lookup("mod3") if tpl2 != nil { tpl2.Execute(os.Stdout, nil) }
輸出:
我是mod3_我是mod1_我是mod2_標題
總結:
1、一個模板對象,可以有多個“名稱”,但是通過 .Name() 方法,只返回最后一次通過 .New() 方法新建的“名稱”。特別注意:此時的 模板對象 的 數據段也是指向該“名稱”所綁定的“字符串”數據;
2、一個模板對象,可以有多個“名稱”,但是他們是相互獨立的,每個“名稱”,通過 .Parse() 方法,可以與一段“字符串”數據對象建立關聯。也就是說,后期通過 .Lookup("某個名稱") 方法獲取到的(模板)對象,其當前數據段,指向該“字符串”,再通過 .Execute() 方法輸出的內容,也是跟該“字符串”相關的內容;
3、在某個“名稱”的數據“字符串”對象中,可以用 define 定義子模塊名,如 {{define "子模塊名"}}子模塊內容{{end}},該 “子模塊”又獨立於 當前“名稱”,即 當前“名稱”的輸出內容,不包含 “子模板”的內容,參考 示例3
只輸出“我是mod2_內容”,並沒有輸出“我是mod2_標題”
4、特別注意,通過 {{define "子模塊名"}}子模塊內容{{end}} 定義的名稱,並不是 模板對象 的一個“名稱”,但是我們同樣可以用 .Lookup("某個名稱") 方法獲取到對象,其當前數據段,指向該 “子模塊”,再通過 .Execute() 方法輸出的內容,也是跟該“子模塊”相關的內容,查看 示例4
只輸出“我是mod2_標題”
5、可用重復定義“名稱”和 “子模塊”,但后面定義的會覆蓋前面定義的,即 只有最后一次定義的有效。參考 示例6
6、模板內容(“名稱”的“字符串”對象)中,可通過 template 關鍵字來 引用/包含 “名稱”和 “子模塊”,如 {{template "名稱/子模塊"}},參考 示例7
搞明白了這些基礎知識,再回過頭看 Beego 的模板模塊,已是非常簡單了!