【Golang】【 Network programming with Go】 Templates(模版(1)

img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

{{end}}

{{with .Jobs}}
{{range .}}
An employer is {{.Employer}}
and the role is {{.Role}}
{{end}}
{{end}}
`

func main() {
job1 := Job{Employer: “Monash”, Role: “Honorary”}
job2 := Job{Employer: “Box Hill”, Role: “Head of HE”}

    person := Person{
            Name:   "jan",
            Age:    50,
            Emails: []string{"jan@newmarch.name", "jan.newmarch@gmail.com"},
            Jobs:   []*Job{&job1, &job2},
    }

    t := template.New("Person template")
    t, err := t.Parse(templ)
    checkError(err)

    err = t.Execute(os.Stdout, person)
    checkError(err)

}

func checkError(err error) {
if err != nil {
fmt.Println("Fatal error ", err.Error())
os.Exit(1)
}
}


  
 


输出如下:



The name is jan.
The age is 50.

    An email is jan@newmarch.name

    An email is jan.newmarch@gmail.com




    An employer is Monash
    and the role is Honorary

    An employer is Box Hill
    and the role is Head of HE

  
 


注意,上面有很多空白的输出,这是因为我们的模板中有很多空白。如果想消除它, 模板设置如下:



{{range .Emails}} An email is {{.}} {{end}}


  
 


在这个示例例中,我们用字符串应用于模板。你同样也可以用方法`template.ParseFiles()`来从文件中下载模板。因为某些原因,我还不没搞清楚(在早期版本没有强制要求),关联模板的名字必须要与文件列表的第一个文件的基名相同。话说,这个是BUG吗?


### Pipelines


### 管道


  
 


上述转换到模板中插入的文本块。这些字符基本上是任意的,是任何字符串的字段值。如果我们希望它们出现的是HTML文档(或其他的特殊形式)的一部分,那么我们将不得不脱离特定的字符序列。例如,要显示任意文本在HTML文档中,我们要将“<”改成“&lt”。GO模板有一些内建函数,其中之一是`html`。这些函数的作用与Unix的管道类似,从标准输入读取和写入到标准输出。


  
 


如果想用“.”来获取当前对象值并且应用于HTML转义,你可以在模板里写个“管道”:



{{. | html}}


  
 


其他方法类似。


  
 


Mike Samuel指出,目前在`exp/template/html` 包里有一个方便的方法。如果所有的模板中的条目需要通过`html` 模板函数,那么Go语言方法 `Escape(t *template.Template)`就能获取模板而后将`html` 函数添加到模板中不存在该函数的每个节点中。用于HTML文档的模板是非常有用的,并能在其他使用场合生成相似的方法模式。


### Defining functions


### 定义方法


  
 


模板使用对象化的字符串表示形式插入值,使用`fmt`包将对象转换为字符串。有时候,这并不是必需。例如,为了避免被垃圾邮件发送者掌握电子邮件地址,常见的方式是把字符号“@”替换为“at”,如“jan at newmarch.name”。如果我们要使用一个模板,显示在该表单中的电子邮件地址,那么我们就必须建立一个自定义的功能做这种转变。


  
 


每个模板函数中使用的模板本身有的一个名称,以及相关联的函数。他们用下面方式进行关联如下



type FuncMap map[string]interface{}


  
 


例如,如果我们希望我们的模板函数是“emailExpand”,用来关联到Go函数`EmailExpander`,然后,我们像这样添加函数到到模板中



t = t.Funcs(template.FuncMap{“emailExpand”: EmailExpander})


  
 


`EmailExpander`通常像这样标记:



func EmailExpander(args …interface{}) string


  
 


我们感兴趣的是在使用过程中,那是一个只有一个参数的函数,并且是个字符串。在Go模板库的现有功能有初步的代码来处理不符合要求的情况,所以我们只需要复制。然后,它就能通过简单的字符串操作来改变格式的电子邮件地址。程序如



/**
* PrintEmails
*/

package main

import (
“fmt”
“os”
“strings”
“text/template”
)

type Person struct {
Name string
Emails []string
}

const templ = The name is {{.Name}}. {{range .Emails}} An email is "{{. | emailExpand}}" {{end}}

func EmailExpander(args …interface{}) string {
ok := false
var s string
if len(args) == 1 {
s, ok = args[0].(string)
}
if !ok {
s = fmt.Sprint(args…)
}

    // find the @ symbol

substrs := strings.Split(s, “@”)
if len(substrs) != 2 {
return s
}
// replace the @ by " at "
return (substrs[0] + " at " + substrs[1])
}

func main() {
person := Person{
Name: “jan”,
Emails: []string{“jan@newmarch.name”, “jan.newmarch@gmail.com”},
}

    t := template.New("Person template")

    // add our function

t = t.Funcs(template.FuncMap{“emailExpand”: EmailExpander})

    t, err := t.Parse(templ)

    checkError(err)

    err = t.Execute(os.Stdout, person)
    checkError(err)

}

func checkError(err error) {
if err != nil {
fmt.Println("Fatal error ", err.Error())
os.Exit(1)
}
}


The output is


输出为:



The name is jan.

    An email is "jan at newmarch.name"

    An email is "jan.newmarch at gmail.com"

### Variables


### 变量


  
 


template包,允许您定义和使用变量。这样做的动机,可能我们会考虑通过把他们的名字当做电子邮件地址*前缀*打印出来。我们又使用这个类型



type Person struct {
Name string
Emails []string
}


  
 


为了访问email的所有字符串, 可以用 `range`,如下



{{range .Emails}}
{{.}}
{{end}}


  
 


但是需要指出的是,我们无法用'.' 的形式来访问字段 `Name`,因为当他被转化成数组元素时,字段`Name`并不包括其中。解决方法是,将字段`Name` 存储为一个变量,那么它就能在任意范围内被访问。变量在模板中用法是加前缀'$'。所以可以这样



{{KaTeX parse error: Expected 'EOF', got '}' at position 14: name := .Name}̲} {{range .Emai…name}}, email is {{.}}
{{end}}


  
 


程序如下:



/**
* PrintNameEmails
*/

package main

import (
“html/template”
“os”
“fmt”
)

type Person struct {
Name string
Emails []string
}

const templ = {{$name := .Name}} {{range .Emails}} Name is {{$name}}, email is {{.}} {{end}}

func main() {
person := Person{
Name: “jan”,
Emails: []string{“jan@newmarch.name”, “jan.newmarch@gmail.com”},
}

    t := template.New("Person template")
    t, err := t.Parse(templ)
    checkError(err)

    err = t.Execute(os.Stdout, person)
    checkError(err)

}

func checkError(err error) {
if err != nil {
fmt.Println("Fatal error ", err.Error())
os.Exit(1)
}
}


  
 


输出为



Name is jan, email is jan@newmarch.name

Name is jan, email is jan.newmarch@gmail.com

### Conditional statements


### 条件语句


  
 


继续我们那个`Person`的例子,假设我们只是想打印出来的邮件列表,而不关心其中的字段。我们可以用模板这么干



Name is {{.Name}}
Emails are {{.Emails}}


输出为:



Name is jan
Emails are [jan@newmarch.name jan.newmarch@gmail.com]


 


因为这个`fmt`包会显示一个列表。


 


在许多情况下,这样做也没有问题,如果那是你想要的。让我们考虑下一种情况,它 *几乎*是对的但不是必须的。有一个JSON序列化对象的包,让我们看看第4章。它是这样的



{“Name”: “jan”,
“Emails”: [“jan@newmarch.name”, “jan.newmarch@gmail.com”]
}


 


JSON包是一个你会在实践中使用,但是让我们看看我们是否能够使用JSON输出模板。我们可以做一些我们有的类似的模板。这*几乎*就是一个JSON串行器: 



{“Name”: “{{.Name}}”,
“Emails”: {{.Emails}}
}


 


像这样组装



{“Name”: “jan”,
“Emails”: [jan@newmarch.name jan.newmarch@gmail.com]
}


 


其中有两个问题:地址没有在引号中,列表中的元素应该是','分隔。


 


这样如何:在数组中的元素,把它们放在引号中并用逗号分隔?



{“Name”: {{.Name}},
“Emails”: [
{{range .Emails}}
“{{.}}”,
{{end}}
]
}


It will produce


像这样组装



{“Name”: “jan”,
“Emails”: [“jan@newmarch.name”, “jan.newmarch@gmail.com”,]
}


 


(再加上一些空白)。


 


同样,这样貌似几乎是正确的,但如果你仔细看,你会看到尾有“,”在最后的列表元素。根据JSON的语法(请参阅<http://www.json.org/>,这个结尾的','是不允许的。这样实现结果可能会有所不同。


 


我们想要打印所有在后面带','的元素除了最后一个。"这个确实有点难搞, 一个好方法"在',' *之前*打印所有元素除了*第一个*。" (我在 "brianb"的  [Stack Overflow](https://bbs.csdn.net/topics/618658159)上提了建议)。这样更易于实现,因为第一个元素索引为0,很多编程语言包括GO模板都将0当做布尔型的`false`。


 


条件语句的一种形式是`{{if pipeline}} T1 {{else}} T0 {{end}}`。我们需要通过`pipeline`来获取电子邮件到数组的索引。幸运的是, `range`的变化语句为我们提供了这一点。有两种形式,引进变量



{{range $elmt := array}}
{{range $index, $elmt := array}}


 


所以我们遍历数组,如果该索引是false(0),我们只是打印的这个索引的元素,否则打印它前面是','的元素。模板是这样的


![img](https://img-blog.csdnimg.cn/img_convert/e7d480f12c4bc198f200d20a948d86bb.png)
![img](https://img-blog.csdnimg.cn/img_convert/69f97536364bf2146e2ebe012535a741.png)
![img](https://img-blog.csdnimg.cn/img_convert/3c922932b20c7308b78375ae15abf288.png)

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618658159)**

种形式是`{{if pipeline}} T1 {{else}} T0 {{end}}`。我们需要通过`pipeline`来获取电子邮件到数组的索引。幸运的是, `range`的变化语句为我们提供了这一点。有两种形式,引进变量



{{range $elmt := array}}
{{range $index, $elmt := array}}


 


所以我们遍历数组,如果该索引是false(0),我们只是打印的这个索引的元素,否则打印它前面是','的元素。模板是这样的


[外链图片转存中...(img-ApRAkxi1-1715535015151)]
[外链图片转存中...(img-Wxcg6mSO-1715535015151)]
[外链图片转存中...(img-tAc8lWsY-1715535015152)]

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618658159)**

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值