go 模板详说
<p>模板是我们常用的手段用于动态生成页面,或者用于代码生成器的编写等。比如把数据库的表映射成<code>go</code>语言的<code>struct</code>,这些体力活,写个代码生成器是最合适不过的了.<br>示例把表转成 struct :<br>
这里--> go模板-代码生成器</p>
<p><img src="https://img2020.cnblogs.com/blog/342595/202005/342595-20200506114623005-2058622212.png" alt="" loading="lazy"></p>
<p>当然这篇帖子不是写关于代码生成器的,是详细说一下<code>go</code>的<code>Template</code>,对<code>Template</code>的操作熟悉了后,就可以利用他实现你想要的一些功能。</p>
<h2 id="渲染对象">渲染对象</h2>
<p><code>{{.}}</code>来渲染对象本身,对象内部的字段可以<code>{{.field}}</code><br>
比如下面,我是用一个 <code>map</code>来存储的数据,访问key: <code>name</code>,并使用<code>{{.}}</code>来把 <code>map</code>打印出来<br>
eg:</p>
<pre><code> tmpl, err := template.New("test").Parse(`hello {{.name}}!
obj: {{.}}`)
if err != nil {
panic(err)
}
err = tmpl.Execute(os.Stdout, mapinterface{}{
"name": "world", "age": 18})
if err != nil {
panic(err)
}
</code></pre>
<p>输出</p>
<pre><code>hello world!
obj: map
</code></pre>
<p>结构体内的字段也是用<code>{{.field}}</code></p>
<pre><code> tmpl, err := template.New("test").Parse(`hello {{.Name}}!
obj: {{.}}`)
if err != nil {
panic(err)
}
err = tmpl.Execute(os.Stdout, struct {
Name string
Ageint
}{Name: "li", Age: 18})
if err != nil {
panic(err)
}
</code></pre>
<h3 id="空格">空格</h3>
<p>在<code>{{}}</code>内添加 <code>-</code>可以去掉空格</p>
<ul>
<li><code>{{- }}</code> 去掉左边所有的空格</li>
<li><code>{{ -}}</code> 去掉右边所有的空格</li>
<li><code>{{- -}}</code> 去掉两边所有的空格<br>
<code>eg:</code></li>
</ul>
<pre><code> 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
Ageint
}{Name: "li", Age: 18})
if err != nil {
panic(err)
}
</code></pre>
<ul>
<li><code>hello:</code> 后面的空格到<code>{{- .Name}}</code> 之间的空格会被去掉.</li>
<li><code>{{.Age -}}</code>到 <code>!!!</code>之间的空格会被去掉</li>
<li><code>obj:</code>到<code>{{- . -}}</code>到 <code>end.</code>之间的空格都会被去掉。</li>
</ul>
<pre><code>hello:li
age: 18!!!
obj:{li 18}end.
</code></pre>
<h3 id="自定义变量">自定义变量</h3>
<p>除了可以直接使用<code>go</code>的对象,也可以直接在模板中定义变量<code>{{ $var := }}</code>,变量定义后,可以在模板内其他任意地方使用:</p>
<pre><code> 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)
}
</code></pre>
<p>输出</p>
<pre><code>hello li
</code></pre>
<h2 id="方法">方法</h2>
<p>方法可以分为全局方法和结构体方法还有内置方法,内置方法也是全局方法的一种</p>
<h3 id="全局方法">全局方法</h3>
<p><code>template.FuncMap</code> 是一个<code>map</code>里面的<code>value</code>必需是方法,传入的值的参数没有限制</p>
<pre><code>type FuncMap mapinterface{}
</code></pre>
<p>比如:定义一个<code>ReplaceAll</code>方法,替换所有的指定字符串<br>
例子中把所有的<code>zhang</code>替换成<code>li</code></p>
<pre><code> 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
Ageint
}{Name: "zhang_san zhang_si", Age: 18})
if err != nil {
panic(err)
}
</code></pre>
<p>输出</p>
<pre><code>func replace:li_san li_si
</code></pre>
<h4 id="内置方法">内置方法</h4>
<p>模板有一些内置方法比如 <code>call</code> <code>printf</code> 等,和全局方法一样,直接调用就行</p>
<pre><code> 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
Ageint
}{Name: "li", Age: 18})
if err != nil {
panic(err)
}
</code></pre>
<p>输出</p>
<pre><code>name: li age: 18
</code></pre>
<h2 id="行为">行为</h2>
<p>常用的行为有<code>if</code> <code>range</code> <code>template</code>等</p>
<h3 id="if">if</h3>
<p>判断 <code>{{if }}{{end}}</code>,可以用于<code>字符串</code> <code>bool</code> 或者<code>数值类型</code><br>
当 <code>字符串有数据</code> 或者<code>bool</code>值为<code>true</code> 或者<code>数值类型</code>大于<code>0</code> 时为真</p>
<pre><code> 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)
}
</code></pre>
<p>输出:</p>
<pre><code> name:
string .Name false
desc: xyz
string .Desc true
age: 18
number .Age true
isAdmin: true
bool .IsAdmin true
</code></pre>
<h3 id="range">range</h3>
<p><code>range</code> 用于遍例数组,和<code>go</code>的 <code>range</code>一样,可以直接得到每个变量,或者得到 <code>index</code> 和<code>value</code></p>
<pre><code> 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, mapinterface{}{
"val": []string{"a", "b", "c", "d"}})
if err != nil {
panic(err)
}
</code></pre>
<p>输出</p>
<pre><code>abcd
id: 0: aid: 1: bid: 2: cid: 3: d
</code></pre>
<h3 id="内嵌template">内嵌template</h3>
<p>除了可以在自定义对象还可以自定义内嵌的模板<code>{{define "name"}}</code>,也可以传参数</p>
<pre><code> 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)
}
</code></pre>
<p>在调用时<code>{{template "content" "zhang san"}}</code> 传递了参数 <code>zhang san</code><br>
输出:</p>
<pre><code>content:hello zhang san
</code></pre>
<h3 id="注释">注释</h3>
<p>模板的注释: <code>{{/* comment */}}</code></p>
<pre><code> 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)
}
</code></pre>
</div>
<div id="MySignature" role="contentinfo">
<div id="AllanboltSignature">
<div>作者:李鹏</div>
<div>出处:http://www.cnblogs.com/li-peng/</div>
<div>本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。 </div>
</div><br><br>
来源:https://www.cnblogs.com/li-peng/p/12835425.html
頁:
[1]