为了账号安全,请及时绑定邮箱和手机立即绑定

65.模板详细使用(一)

标签:
Go

模板是构建丰富结构的web页面的主要手段。所以需要再深入了解一下。
首先构建一个handler

func templateHandler(writer http.ResponseWriter, request *http.Request) {
    t, err := template.ParseFiles("./JoelTempWeb/layout.html")    if err != nil{
        fmt.Fprintln(writer,err)
    }
    fmt.Println("template name is ",t.Name())
    t.Execute(writer,"hello moon")

}

当然需要配套的html模板

<!DOCTYPE html><html lang="en"><head>
    <meta charset="UTF-8">
    <title>layout</title></head><body><h3>This is layout</h3>template data:{{ . }}</body></html>

这里的 {{.}}就是显示func templateHandler中的给出的数据 "hello moon" 的。所以,当main里这样之后

http.HandleFunc("/layout/", templateHandler)
http.ListenAndServe(":8090", nil)

运行结果如下


webp

hello moon的示例


完整main代码

package mainimport (    "fmt"
    "joeltest/JoelTempWeb")func main()  {
    JoelTempWeb.JoelHttpPath()
    JoelTempWeb.JoelListenAndServe()
}

完整JoelTempWeb代码

package JoelTempWebimport (    "net/http"
    "time"
    "html/template"
    "fmt"
    "math/rand"
    "strconv"
    "math")//Joel路径func JoelHttpPath() {
    http.HandleFunc("/layout/", templateHandler)
}//Joel监听func JoelListenAndServe() {
    http.ListenAndServe(":8090", nil)
}//=================================func templateHandler(writer http.ResponseWriter, request *http.Request) {
    t, err := template.ParseFiles("./JoelTempWeb/layout.html")    if err != nil{
        fmt.Fprintln(writer,err)
    }
    fmt.Println("template name is ",t.Name())
    t.Execute(writer,"hello moon")
}//--------------------------------

模板页layout

<!DOCTYPE html><html lang="en"><head>
    <meta charset="UTF-8">
    <title>layout</title></head><body><h3>This is layout</h3>template data:{{ . }}</body></html>

模板还是可以命名的,命名的方式是

t.ExecuteTemplate(writer, "layout", "Hello Moon!!!")

这样,这个模板的名字就是 layout 了。
那么在模板页面中,可以添加 define 来指定 action 的名字。
于是,在模板文件中,可以添加

{{define "layout"}}
{{end}}

webp

内容是一样显示的


layout.html的代码变成了这样

{{define "layout"}}<!DOCTYPE html><html lang="en"><head>
    <meta charset="UTF-8">
    <title>layout</title></head><body><h3>This is layout</h3>template data:{{ . }}</body></html>{{end}}

在页面的结构中,可以引入多个模板。比如,我们在引入一个index.html

{{define "index"}}
<div style="background-color: chocolate;width: 555px">    this is index.html
{{.}}
</div>
{{end}}

那么在 func templateHandler 中就要修改成这个样子

func templateHandler(writer http.ResponseWriter, request *http.Request) {
    t, err := template.ParseFiles("./JoelTempWeb/layout.html","./JoelTempWeb/index.html")    if err != nil{
        fmt.Fprintln(writer,err)
    }
    fmt.Println("template name is ",t.Name())
    t.ExecuteTemplate(writer, "layout", "Hello Moon!!!")
}

因为 index.html 中 define "index" 了,所以,在 layout.html 中加入 index模板的时候就可以直接写 template "index"

{{define "layout"}}<!DOCTYPE html><html lang="en"><head>
    <meta charset="UTF-8">
    <title>layout</title></head><body><h3>This is layout</h3>template data:{{ . }}
{{template "index"}}</body></html>{{end}}

webp

这个巧克力色的行,就是index模板添加进来的效果了


当然,如果你把 t.ExecuteTemplate(writer, "layout", "Hello Moon!!!")中的 layout 改为 index ,你就会发现,只剩下index模板的内容了。并且因为使用了index的名字,所以index模板中的 {{.}}也开始起作用了,获得了data


webp

只剩下一行了

直接写字符串模板

模板是可以自己new一个的。不必要存在一个真实的html文件。可以只给出一个名字,这个名字是html文件后缀式的。比如:tmpl.html
请看代码

func Joeltemplate3(writer http.ResponseWriter, request *http.Request) {
    tmpl := `<!DOCTYPE html><html>
    <head>
        <meta http-qquiv="Content-Type" content="text/html; charset=utf-8">
        <title>Go Web Programming</title>
    </head>
    <body>
        {{.}}    </body></html>`
    t := template.New("tmpl.html")
    t, _ = t.Parse(tmpl)
    t.Execute(writer, "Hello Moon !!!")
}

在main里http.HandleFunc这个函数就可以了。

    http.HandleFunc("/mm/", JoelTempFunc.Joeltemplate3)
    server := http.Server{Addr:":8090"}
    server.ListenAndServe()

执行结果


webp

直接写字符串模板的执行结果

执行模板

如果有多个模板,你只想在执行的时候,才确定执行某一个模板,就需要能够自由的制定要执行的模板。那么要使用到模板名。
当 template.ParseFiles 的参数有多个模板的时候,Execute 方法只会执行第一个模板

    t, _ := template.ParseFiles("./JoelTemplate/sayHello.html","./JoelTemplate/sayHelloSon.html")
    t.Execute(writer, "最爱的是明月")

如果要指定执行第二个模板,这个时候要使用模板名。第二个模板的模板名不包含模板的路径。而且,要想使用模板名指定执行模板的方式,就不能使用 Execute 了,而应该使用 ExecuteTemplate

func Joeltemplate4(writer http.ResponseWriter, request *http.Request) {
    t, _ := template.ParseFiles("./JoelTemplate/sayHello.html","./JoelTemplate/sayHelloMoon.html")
    t.ExecuteTemplate(writer,"sayHelloMoon.html", "最爱的是明月")
}

sayHelloMoon.html模板代码

<!DOCTYPE html><html lang="en"><head>
    <meta charset="UTF-8">
    <title>sayHello Title</title></head><body>每天要问候:{{.}}<hr></body></html>

webp

执行模板

条件动作

根据条件选择要执行的动作,格式是

{{if arg}}
    some content
{{end}}

当然,if else end 的模式也是存在的。

{{if arg}}
    some content
{{else}}
    other content
{{end}}

根据这个逻辑,写一个随机数,以数字5为界,大于5或相反,显示不同的内容。
代码示例

//条件动作func processIfHandler(writer http.ResponseWriter, request *http.Request) {
    t, _ := template.ParseFiles("./JoelTempWeb/tmpl.html")
    rand.Seed(time.Now().Unix())
    t.ExecuteTemplate(writer, "tmpl", rand.Intn(10)>5)
}

在main里添加这个

http.HandleFunc("/processif/", processIfHandler)

模板这样写

{{define "tmpl"}}<!DOCTYPE html><html lang="en"><head>
    <meta charset="UTF-8">
    <title>Go Web Programming</title></head><body><h3>This is random than 5</h3>{{if .}}
就是Moon 大于 5
{{else}}
不是Moon 小于等于 5
{{end}}</body></html>{{end}}

这里的模板调用有个技巧。因为模板文件 define 了名字为 tmpl,所以在加载模板的时候,要这样写

t.ExecuteTemplate(writer, "tmpl", rand.Intn(10)>5)

webp

大于5


webp

小于等于5

迭代动作

可以对数组、切片、映射或者通道进行迭代,在迭代循环内把{{.}}显示为当前迭代的元素。使用 range 关键字实现。像这样

{{range array}}
    这里是循环元素显示{{.}}
{{end}}

来个对星期的模板加载的迭代动作

//迭代动作func processIterationHandler(writer http.ResponseWriter, request *http.Request) {
    t, _ := template.ParseFiles("./JoelTempWeb/tmplrange.html")
    dayofweek := []string{"星期日","星期一","星期二","星期三","星期四","星期五","星期六",}
    t.ExecuteTemplate(writer, "range", dayofweek)
}

在main里要添加这个

http.HandleFunc("/processIteration/", processIterationHandler)

模板文件

{{define "range"}}<!DOCTYPE html><html lang="en"><head>
    <meta charset="UTF-8">
    <title>Go Web Programming</title></head><body><h3>This is range</h3><ul>{{range .}}    <li>{{.}}</li>{{end}}</ul><table style="border-collapse:collapse;">{{range .}}    <tr >
        <td style="border:1px solid orange;">{{.}}</td>
    </tr>{{end}}</table></body></html>{{end}}

为了好看一点,加了点table样式。


webp

即使你的服务器是windows,路径也是区分大小写的


也可以在模板中添加一个变化,判断有没有数据,没有数据的话显示一个特定的信息。这需要使用 else ,方式类似if else end,是 range else end。

{{define "range"}}<!DOCTYPE html><html lang="en"><head>
    <meta charset="UTF-8">
    <title>Go Web Programming</title></head><body><h3>This is range</h3><ul>{{range .}}    <li>{{.}}</li>{{end}}</ul><table style="border-collapse:collapse;">{{range .}}    <tr >
        <td style="border:1px solid orange;">{{.}}</td>
    </tr>
    {{else}}    <tr >
        <td style="border:1px solid orange;">暂时没有数据...</td>
    </tr>{{end}}</table></body></html>{{end}}

然后把函数修改一下,去掉数组里的数据。

//迭代动作
func processIterationHandler(writer http.ResponseWriter, request *http.Request) {
    t, _ := template.ParseFiles("./JoelTempWeb/tmplrange.html")
    //dayofweek := []string{"星期日","星期一","星期二","星期三","星期四","星期五","星期六",}
    dayofweek := []string{}
    t.ExecuteTemplate(writer, "range", dayofweek)
}



执行结果是这样的

webp

暂时没有数据

设置动作

可以在模板中重新设置参数的值。使用 with 关键字,代码结构像这样

{{with arg}}    set to arg
{{end}}

也可以添加 else,结构像这样

{{with arg}}    set to arg
{{else}}
   still old arg
{{end}}

现在看一下模板代码示例

{{define "with"}}<!DOCTYPE html><html lang="en"><head>
    <meta charset="UTF-8">
    <title>Go Web Programming</title></head><body><h3>This is with</h3><table style="border-collapse:collapse;">{{with "Moon"}}    <tr >
        <td style="border:1px solid orange;">爱{{.}}</td>
    </tr>{{else}}    <tr >
        <td style="border:1px solid orange;">原来的数据{{.}}</td>
    </tr>{{end}}</table></body></html>{{end}}

执行结果


webp

with "Moon"


如果with后面的内容是空的,那么就是执行else的内容了。

{{define "with"}}<!DOCTYPE html><html lang="en"><head>
    <meta charset="UTF-8">
    <title>Go Web Programming</title></head><body><h3>This is with</h3><table style="border-collapse:collapse;">{{with ""}}    <tr >
        <td style="border:1px solid orange;">爱{{.}}</td>
    </tr>{{else}}    <tr >
        <td style="border:1px solid orange;">原来的数据{{.}}</td>
    </tr>{{end}}</table></body></html>{{end}}

with内容为空的执行结果

webp

with ""


\color{#9900ff}{注意:}

如果你在模板中使用了 define 定义模板名,在代码中,就必须使用
t.ExecuteTemplate(writer,"arg", map[string]string{"星期一":"Monday"})这样的语法


参数、变量、管道

在go语言中,模板参数也可以是各种形式的值,比如:布尔值、整数、字符串、结构、结构中的一个字段、数组中的一个键、一个变量、一个方法(有且只有一个返回值或再加上一个返回错误)、一个函数、或者一个点(.)。
就好像这样的代码

{{if arg}}
    some content
{{end}}

在动作中设置变量,是以美元符号$开头,就像这样:

$variable := value

这样看似乎变量没什么大用,但是,如果是下面这样呢?

{{range $key, $value := . }}
    Key = {{ $key }}; Value = {{ $value }}
{{end}}

变量实际上对动作来说,是非常重要的。
参看示例代码

//参数、变量、管道func processArgHandler(writer http.ResponseWriter, request *http.Request) {
    t, _ := template.ParseFiles("./JoelTempWeb/tmplArg.html")
    t.ExecuteTemplate(writer,"arg", map[string]string{"星期一":"Monday"})
}

这里的data是一个map映射,要传递到模板tmplArg.html组合后返回html代码。
模板代码

{{define "arg"}}<!DOCTYPE html><html lang="en"><head>
    <meta charset="UTF-8">
    <title>Go Web Programming</title></head><body><h3>This is Arg/value/channel</h3><table style="border-collapse:collapse;">{{range $key, $value := .}}    <tr>
        <td style="border:1px solid orange;">Key = {{ $key }};Value = {{ $value }}</td>
    </tr>{{end}}</table><h3>This is include</h3></body></html>{{end}}

在main函数中加入下面的代码

http.HandleFunc("/processArg/", processArgHandler)

执行结果如下


webp

参数、变量


这样写map当然在实际项目代码中不会这么弄了。那么,看一下这段代码

func Joeltemplate5(writer http.ResponseWriter, request *http.Request) {
    t, _ := template.ParseFiles("./JoelTemplate/sayHelloDay.html")
    weekday := map[string]string{"Sunday":"星期日", "Monday":"星期一", "Tuesday":"星期二", "Wednesday":"星期三", "Thursday":"星期四", "Friday":"星期五", "Saturday":"星期六"}

    t.ExecuteTemplate(writer,"sayHelloDay.html", weekday)
}

这样,就会随机的把map中的key 和 value 都显示出来了。而且,代码更符合实际编码的习惯。在给值前对map内的元素进行编辑。
模板中的管道是多个有序串联起来的参数。参数以 “|” 符号分隔。管道允许用户将一个参数的输出传递给下一个参数。比如,一个值为浮点数的参数,在模板中进行格式化,就像这样

{{ 2014.10171695 | printf "%.2f"}}

执行后,会得到 2014.10
代码如下

func Joeltemplate6(writer http.ResponseWriter, request *http.Request) {
    t, _ := template.ParseFiles("./JoelTemplate/sayHelloPipe.html")
    /*cmd1 := exec.Command("love","shun","sun")
    stdout1, err := cmd1.StdinPipe()    if err != nil {
        t.ExecuteTemplate(writer, "sayHelloPipe.html", err)
    }else{
        t.ExecuteTemplate(writer, "sayHelloPipe.html", stdout1)
    }*/
    var nf float64 = 2014.10171695t.ExecuteTemplate(writer, "sayHelloPipe.html", nf)
}

模板文件sayHelloPipe.html代码

<!DOCTYPE html><html lang="en"><head>
    <meta charset="UTF-8">
    <title>Go Web Programming</title></head><body>
  {{.|printf "%.2f"}}</body></html>

在main中 http.HandleFunc("/uu/", JoelTempFunc.Joeltemplate6)
然后就可以在 路径 uu 里看到执行结果了


webp

%.2f


然后,我没知道实际的值在小数点后面还有很多位,当需要显示更大精度的浮点数的时候,不需要修改 go 代码,只修改模板文件里的通道参数就可以了。

{{.|printf "%.2f"}}
改为
{{.|printf "%.4f"}}

保存模板后,执行结果是


webp

%.4f



作者:厚土火烟
链接:https://www.jianshu.com/p/e5736e618471


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消