go語言的模板,text/template包

#go語言的模板,text/template包 ##定義 模板就是將一組文本嵌入另外一組文本里ui

##傳入string--最簡單的替換code

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的值,只要使用成員名字便可,看代碼吧:get

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,Lookupstring

//一個模板能夠有多種,以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

##文件模板,介紹ParseFilesit

//模板能夠是一行
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自動爲文件名

##文件模板,介紹ParseGlobtest

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

假設一個目錄裏有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行空白
相關文章
相關標籤/搜索