go語言的模板,text/template包


go語言的模板,text/template包

定義

模板就是將一組文本嵌入另一組文本里

傳入string--最簡單的替換

package main import ( "os" "text/template" ) func main() { name := "waynehu" tmpl, err := template.New("test").Parse("hello, {{.}}") //建立一個模板,內容是"hello, {{.}}" if err != nil { panic(err) } err = tmpl.Execute(os.Stdout, name) //將string與模板合成,變量name的內容會替換掉{{.}} //合成結果放到os.Stdout里 if err != nil { panic(err) } } //輸出 : hello, waynehu 

因為"hello, {{.}}"也是一個字符串,所以可以單獨拎出來,如下:

//這句
tmpl, err := template.New("test").Parse("hello, {{.}}") //等於下面的兩句 muban := "hello, {{.}}" tmpl, err := template.New("test").Parse(muban) //之后的例子都用兩句的方式表達 

傳入struct

模板合成那句,第2個參數是interface{},所以可以傳入任何類型,現在傳入struct看看 要取得struct的值,只要使用成員名字即可,看代碼吧:

package main import ( "os" "text/template" ) type Inventory struct { Material string Count uint } func main() { sweaters := Inventory{"wool", 17} muban := "{{.Count}} items are made of {{.Material}}" tmpl, err := template.New("test").Parse(muban) //建立一個模板 if err != nil { panic(err) } err = tmpl.Execute(os.Stdout, sweaters) //將struct與模板合成,合成結果放到os.Stdout里 if err != nil { panic(err) } } //輸出 : 17 items are made of wool 

多模板,介紹New,Name,Lookup

//一個模板可以有多種,以Name來區分 muban_eng := "{{.Count}} items are made of {{.Material}}" muban_chn := "{{.Material}}做了{{.Count}}個項目" //建立一個模板的名稱是china,模板的內容是muban_chn字符串 tmpl, err := template.New("china") tmpl, err = tmpl.Parse(muban_chn) //建立一個模板的名稱是english,模板的內容是muban_eng字符串 tmpl, err = tmpl.New("english") tmpl, err = tmpl.Parse(muban_eng) //將struct與模板合成,用名字是china的模板進行合成,結果放到os.Stdout里,內容為“wool做了17個項目” err = tmpl.ExecuteTemplate(os.Stdout, "china", sweaters) //將struct與模板合成,用名字是china的模板進行合成,結果放到os.Stdout里,內容為“17 items are made of wool” err = tmpl.ExecuteTemplate(os.Stdout, "english", sweaters) tmpl, err = template.New("english") fmt.Println(tmpl.Name()) //打印出english tmpl, err = tmpl.New("china") fmt.Println(tmpl.Name()) //打印出china tmpl=tmpl.Lookup("english")//必須要有返回,否則不生效 fmt.Println(tmpl.Name()) //打印出english 

文件模板,介紹ParseFiles

//模板可以是一行 muban := "{{.Count}} items are made of {{.Material}}" //也可以是多行 muban := `items number is {{.Count}} there made of {{.Material}} ` 

把模板的內容發在一個文本文件里,用的時候將文本文件里的所有內容賦值給muban這個變量即可
上面的想法可以自己實現,但其實tamplate包已經幫我們封裝好了,那就是template.ParseFiles方法

假設有一個文件mb.txt的內容是muban變量的內容
$cat mb.txt {{.Count}} items are made of {{.Material}} 那么下面2行 muban := "{{.Count}} items are made of {{.Material}}" tmpl, err := template.New("test").Parse(muban) //建立一個模板 等價於 tmpl, err := template.ParseFiles("mb.txt") //建立一個模板,這里不需要new("name")的方式,因為name自動為文件名 

文件模板,介紹ParseGlob

ParseFiles接受一個字符串,字符串的內容是一個模板文件的路徑(絕對路徑or相對路徑)
ParseGlob也差不多,是用正則的方式匹配多個文件

假設一個目錄里有a.txt b.txt c.txt的話 用ParseFiles需要寫3行對應3個文件,如果有一萬個文件呢? 而用ParseGlob只要寫成template.ParseGlob("*.txt") 即可 

模板的輸出,介紹ExecuteTemplate和Execute

模板下有多套模板,其中有一套模板是當前模板
可以使用Name的方式查看當前模板

err = tmpl.ExecuteTemplate(os.Stdout, "english", sweaters) //指定模板名,這次為english err = tmpl.Execute(os.Stdout, sweaters) //模板名省略,打印的是當前模板 

模板的復用

模板里可以套模板,以達到復用目的,用template關鍵字

muban1 := `hi, {{template "M2"}}, hi, {{template "M3"}} ` muban2 := "我是模板2,{{template "M3"}}" muban3 := "ha我是模板3ha!" tmpl, err := template.New("M1").Parse(muban1) tmpl.New("M2").Parse(muban2) tmpl.New("M3").Parse(muban3) err = tmpl.Execute(os.Stdout, nil) 

完整代碼:

package main

import ( "os" "text/template" ) func main() { muban1 := `hi, {{template "M2"}}, hi, {{template "M3"}} ` muban2 := `我是模板2,{{template "M3"}}` muban3 := "ha我是模板3ha!" tmpl, err := template.New("M1").Parse(muban1) if err != nil { panic(err) } tmpl.New("M2").Parse(muban2) if err != nil { panic(err) } tmpl.New("M3").Parse(muban3) if err != nil { panic(err) } err = tmpl.Execute(os.Stdout, nil) if err != nil { panic(err) } } 

輸出的內容

hi, 我是模板2,ha我是模板3ha!, hi, ha我是模板3ha! 

模板的回車

模板文件里的回車也是模板的一部分,如果對回車位置控制不好,合成出來的文章會走樣 標准庫里的Example(Template)寫的還是有點亂,我整理如下:

const letter = `Dear {{.Name}}, {{if .Attended}}It was a pleasure to see you at the wedding. 如果Attended是true的話,這句是第二行{{else}}It is a shame you couldn't make it to the wedding. 如果Attended是false的話,這句是第二行{{end}} {{with .Gift}}Thank you for the lovely {{.}}. {{end}} Best wishes, Josie ` 

解釋一下:

  • Dear某某某的Dear應該是在第一行,所以在D前面不能有回車,否則Dear會跑到第2行去
    • 所以Dear要緊貼```
  • 信件的稱唿和正文有一行空行,最好顯式的打出一行,而標准庫里的回車是包在if里,成為正文的一部分,這樣排版容易出錯
  • 正確的正文排版如下
    • 如果正文就一行,要把true和false的所有內容都寫在一行
      • 比如{{if .Attended}}true line,hello true{{else}}false line,hi false{{end}}
    • 如果正文有多行,就等於把一行拆成多行
      • 會發現true的最后一行和false的第一行是在同一行
      • {{if .Attended}}和ture的第一行在同一行
      • {{end}}和false的最后一行在同一行

如下

{{if .Attended}}true line hello true{{else}}false line hi false{{end}} 
  • 關於{{with .Gift}},意思是如果Gift不是為空的話,就打印整行,如果為空,就不打印
    • 只有這樣寫法,with對應的end要寫在第2行,才會把“Thank you”這句后面帶一個回車進去,這樣寫法,就像“Thank you”這句是插在正文下面的
    • 只有這樣寫,不管有沒有“Thank you”,正文和Best wishes,之間始終只有1行空白


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM