天天看點

go 模闆詳說

模闆是我們常用的手段用于動态生成頁面,或者用于代碼生成器的編寫等。比如把資料庫的表映射成go語言的struct,這些體力活,寫個代碼生成器是最合适不過的了.

示例例把表轉成 struct :

申請阿裡雲服務時,可以使用

2000元阿裡雲代金券 ,阿裡雲官網領取網址: https://dashi.aliyun.com/site/yun/youhui

當然這篇文章不是寫關于代碼生成器的,是詳細說一下go的Template,對Template的操作熟悉了後,就可以利用他實作你想要的一些功能。

渲染對象

{{.}}來渲染對象本身,對象内部的字段可以{{.field}}

比如下面,我是用一個 map來存儲的資料,通路key: name,并使用{{.}}來把 map列印出來

eg:

tmpl, err := template.New("test").Parse(`hello {{.name}}!
obj: {{.}}`)
if err != nil {
    panic(err)
}
err = tmpl.Execute(os.Stdout, map[string]interface{}{
    "name": "world", "age": 18})
if err != nil {
    panic(err)
}           

輸出

hello world!

obj: map[age:18 name:world]

結構體内的字段也是用{{.field}}

tmpl, err := template.New("test").Parse(`hello {{.Name}}!
obj: {{.}}`)
if err != nil {
    panic(err)
}
err = tmpl.Execute(os.Stdout, struct {
    Name string
    Age  int
}{Name: "li", Age: 18})
if err != nil {
    panic(err)
}           

空格

在{{}}内添加 -可以去掉空格

{{- }} 去掉左邊所有的空格

{{ -}} 去掉右邊所有的空格

{{- -}} 去掉兩邊所有的空格

tmpl, err := template.New("test").Parse(`hello:    {{- .Name}}
age: {{.Age -}}   !!!
obj:     
{{- . -}}   end.`)
if err != nil {
    panic(err)
}
err = tmpl.Execute(os.Stdout, struct {
    Name string
    Age  int
}{Name: "li", Age: 18})
if err != nil {
    panic(err)
}           

hello: 後面的空格到{{- .Name}} 之間的空格會被去掉.

{{.Age -}}到 !!!之間的空格會被去掉

obj:到{{- . -}}到 end.之間的空格都會被去掉。

hello:li

age: 18!!!

obj:{li 18}end.

阿裡雲伺服器1核2G低至82元/年

,阿裡雲官活動網址:

https://dashi.aliyun.com/site/yun/aliyun

可以用20代金券,即102-20=82。

自定義變量

除了可以直接使用go的對象,也可以直接在模闆中定義變量{{ $var := }},變量定義後,可以在模闆内其他任意地方使用:

tmpl, err := template.New("test").Parse(`{{$a := "li"}} hello {{$a}}`)
if err != nil {
    panic(err)
}
err = tmpl.Execute(os.Stdout, nil)
if err != nil {
    panic(err)
}           

hello li

方法

方法可以分為全局方法和結構體方法還有内置方法,内置方法也是全局方法的一種

全局方法

template.FuncMap 是一個map裡面的value必需是方法,傳入的值的參數沒有限制

type FuncMap map[string]interface{}

比如:定義一個ReplaceAll方法,替換所有的指定字元串

例子中把所有的zhang替換成li

tmpl, err := template.New("test").Funcs(template.FuncMap{
    "ReplaceAll": func(src string, old, new string) string {
        return strings.ReplaceAll(src, old, new)
    },
}).Parse(`func replace:  {{ReplaceAll .Name "zhang" "li"}}`)
if err != nil {
    panic(err)
}
err = tmpl.Execute(os.Stdout, struct {
    Name string
    Age  int
}{Name: "zhang_san zhang_si", Age: 18})
if err != nil {
    panic(err)
}           

func replace: li_san li_si

内置方法

模闆有一些内置方法比如 call printf 等,和全局方法一樣,直接調用就行

tmpl, err := template.New("test").Parse(`{{printf "name: %s age: %d" .Name .Age}}`)
if err != nil {
    panic(err)
}
err = tmpl.Execute(os.Stdout, struct {
    Name string
    Age  int
}{Name: "li", Age: 18})
if err != nil {
    panic(err)
}           

name: li age: 18

行為

常用的行為有if range template等

if

判斷 {{if }} {{end}},可以用于字元串 bool 或者數值類型

當 字元串有資料 或者bool值為true 或者數值類型大于0 時為真

tmpl, err := template.New("test").Parse(`
name: {{.Name}} 
{{- if .Name}}
  string .Name true 
{{else}} 
  string .Name false 
{{end -}}
desc: {{.Desc}} 
{{- if .Desc}}
  string .Desc true 
{{else}} 
  string .Desc false 
{{end -}}
age: {{.Age}} 
{{- if .Age}}
  number .Age true 
{{else}} 
  number .Age true false
{{end -}}
isAdmin: {{.IsAdmin}} 
{{- if .Age}}
  bool .IsAdmin true 
{{else}} 
  bool .IsAdmin true false
{{end}}
`)
if err != nil {
    panic(err)
}
err = tmpl.Execute(os.Stdout, struct {
    Name    string
    Desc    string
    Age     int
    IsAdmin bool
}{Name: "", Desc: "xyz", Age: 18, IsAdmin: true})
if err != nil {
    panic(err)
}           

輸出:

name:  
  string .Name false 
desc: xyz
  string .Desc true 
age: 18
  number .Age true 
isAdmin: true
  bool .IsAdmin true           

range

range 用于遍例數組,和go的 range一樣,可以直接得到每個變量,或者得到 index 和value

tmpl, err := template.New("test").Parse(`
{{range .val}} {{.}} {{end}}
{{range $idx, $value := .val}} id: {{$idx}}: {{$value}} {{end}}`)
if err != nil {
    panic(err)
}
err = tmpl.Execute(os.Stdout, map[string]interface{}{
    "val": []string{"a", "b", "c", "d"}})
if err != nil {
    panic(err)
}           

a b c d

id: 0: a id: 1: b id: 2: c id: 3: d

内嵌template

除了可以在自定義對象還可以自定義内嵌的模闆{{define "name"}},也可以傳參數

tmpl, err := template.New("test").Parse(`
{{define "content"}} hello {{.}} {{end}}
content: {{template "content" "zhang san"}}`)
if err != nil {
    panic(err)
}
err = tmpl.Execute(os.Stdout, nil)
if err != nil {
    panic(err)
}           

在調用時{{template "content" "zhang san"}} 傳遞了參數 zhang san

content: hello zhang san

注釋

模闆的注釋: {{/ comment /}}

tmpl, err := template.New("test").Parse(`
{{/* 注釋 */}}
{{define "content"}} hello {{.}} {{end}}
content: {{template "content" "zhang san"}}`)
if err != nil {
    panic(err)
}
err = tmpl.Execute(os.Stdout, nil)
if err != nil {
    panic(err)
}