Python有f-string,可以实现模板的功能,但go也有fmt包,可以模板化输出。但是fmt包不够强大,所以GoLang提供了两个template包,text和html包,里面包含了更强大的模板输出能力。我以text/template包举个例子:
package main
import (
"os"
"text/template"
)
type Pet struct {
Name string
Gender string
Species string
Age int
}
func main() {
temp := `名字:{{.Name}}
性别:{{.Gender}}
品种:{{.Species}}
年龄:{{.Age}}岁
`
t, _ := template.New("temp").Parse(temp)
dog := Pet{
Age: 1,
Gender: "雄性",
Species: "兔",
Name: "乖",
}
t.Execute(os.Stdout, dog)
}
输出结果如下:
名字:乖
性别:雄性
品种:兔
年龄:1岁
HTML模板
HTML模板与TEXT模板有很多不同,篇幅有限,我也写不完,只挑一个重要的,就是特殊字符串转义。把上面的例子改一改,加入一些HTML字符:
package main
import (
"html/template"
"os"
)
type Pet struct {
Name string
Gender string
Species string
Age int
}
func main() {
temp := `名字:{{.Name}}
性别:{{.Gender}}
品种:{{.Species}}
年龄:{{.Age}}岁
`
t, _ := template.New("temp").Parse(temp)
dog := Pet{
Age: 1,
Gender: "雄性",
Species: "兔",
Name: "<b>乖</b>",
}
t.Execute(os.Stdout, dog)
}
输出结果中,大于号和小于号都被HTML转义了:
名字:<b>乖</b>
性别:雄性
品种:兔
年龄:1岁
加载文件
上面的例子都是简单的模板,但是如果遇到复杂的模板呢?这个时候需要用到template.ParseFiles函数了,首先先建立一个文件,取名为template.ParseFiles,内容如下:
我养了一条小{{.Species}},TA的名字叫做{{.Name}},他是一个小{{.Gender}}生,今年{{.Age}}岁啦。
然后再GoLang程序中加载这个模板,在将变量传进去,如以下代码:
package main
import (
"fmt"
"os"
"text/template"
)
type Pet struct {
Name string
Gender string
Species string
Age int
}
func main() {
t, _ := template.ParseFiles("demo.tpl")
dog := Pet{
Age: 1,
Gender: "女",
Species: "兔",
Name: "乖",
}
err := t.Execute(os.Stdout, dog)
if err != nil {
fmt.Println(err)
}
}
输出结果:
我养了一条小兔,TA的名字叫做乖,TA是一个小女生,今年1岁啦。
循环
与Java的Freemarker、velocity等模板一样,go的模板也支持循环。如果不支持循环,是不可能是一个可以使用的模板。因为实际项目中,列表式的数据太多了。GoLang模板的循环很简单,以range开始,以end结束,以下是例子:
package main
import (
"html/template"
"os"
)
type Pet struct {
Name string
Gender string
Species string
Age int
}
func main() {
temp := `名字:{{.Name}}
性别:{{.Gender}}
品种:{{.Species}}
年龄:{{.Age}}岁
`
t, _ := template.New("temp").Parse(temp)
dog := Pet{
Age: 1,
Gender: "雄性",
Species: "兔",
Name: "<b>乖</b>",
}
t.Execute(os.Stdout, dog)
}
上述代码的执行结果符合预期:
------------------
名字:乖
性别:雄性
品种:兔
年龄:1岁
------------------
名字:Meow
性别:雌性
品种:猫
年龄:2岁
------------------
名字:汪汪
性别:雄性
品种:犬
年龄:3岁
选择
虽说选择语法,在模板中不是必须的,因为这又可能会使得业务逻辑转移到模板中。学习过MVC开发思想的我们是不想这样开发的。但是有时候选择语法是必须的,假如说奇数行用红色,偶数行用蓝色,这种需求就必须在模板中使用选择语法了,也就是大家常用的if语句。if语句还要配合关系运算符使用,但是GoLang的关系运算符比较特殊,是先写运算符,再参数的,我以小于等于为例子,讲讲这个特性:
package main
import (
"fmt"
"html/template"
"os"
)
type Pet struct {
Name string
Gender string
Species string
Age int
}
func main() {
temp := `{{range .}}------------------
名字:{{.Name}}
性别:{{.Gender}}
品种:{{- if lt .Age 2}}小{{- else}}大{{- end}}{{.Species}}
年龄:{{.Age}}岁
{{end}}
`
t, _ := template.New("temp").Parse(temp)
dog := []Pet{
{
Age: 1,
Gender: "雄性",
Species: "兔",
Name: "乖",
},
{
Age: 2,
Gender: "雌性",
Species: "猫",
Name: "Meow",
},
{
Age: 3,
Gender: "雄性",
Species: "狗",
Name: "汪汪",
},
}
err := t.Execute(os.Stdout, dog)
if err != nil {
fmt.Println(err)
}
}
上述代码中判断小于2是用if lt .Age 2这样的语法,而不是if .Age lt 2,有点不符合平常的语法习惯。但造成这种现象的原因其实是go的模板中,lt是一个函数。上述代码执行结果如下:
------------------
名字:乖
性别:雄性
品种:小兔
年龄:1岁
------------------
名字:Meow
性别:雌性
品种:大猫
年龄:2岁
------------------
名字:汪汪
性别:雄性
品种:大狗
年龄:3岁