【Golang】Go语言Web开发之模板渲染

server/2024/10/20 12:36:25/

在这里插入图片描述

✨✨ 欢迎大家来到景天科技苑✨✨

🎈🎈 养成好习惯,先赞后看哦~🎈🎈

🏆 作者简介:景天科技苑
🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。
🏆《博客》:Python全栈,Golang开发,PyQt5和Tkinter桌面开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi,flask等框架,云原生K8S,linux,shell脚本等实操经验,网站搭建,数据库等分享。

所属的专栏:Go语言开发零基础到高阶实战
景天的主页:景天科技苑

在这里插入图片描述

文章目录

  • Go语言中的模板渲染
    • 一、模板渲染的基本概念
    • 二、模板文件的定义
    • 三、模板的解析与渲染
      • 1. 解析模板文件
      • 2. 模版渲染及输出方式
        • (1)输出到文件
        • (2)输出到变量
        • (3)输出到屏幕
        • (4)输出到页面
      • 3. 从字符串载入模板
    • 四、模板语法
      • 1. 变量
      • 2. 注释
      • 3. 管道
      • 4. 条件判断
      • 5. 循环

Go语言中的模板渲染

在Go语言中,模板渲染是一种强大的工具,用于根据数据动态生成文本输出,特别是在Web开发中,模板渲染能够极大地方便HTML页面的生成。本文将结合实际案例,详细讲解Go语言中模板渲染的用法,包括模板的定义、解析、渲染以及模版语法等高级功能的使用。

一、模板渲染的基本概念

模板渲染是指通过模板引擎,将模板文件和数据结合起来,生成最终的文本输出。在Go语言中,标准库提供了text/templatehtml/template两个包,分别用于生成普通文本和安全的HTML输出。

  • text/template:用于生成普通文本输出。
  • html/template:用于生成安全的HTML输出,防止代码注入攻击。

二、模板文件的定义

模板文件通常是以.tmpl.tpl为后缀的文件,但也可以使用其他后缀。模板文件中包含占位符,用于在渲染时被数据替换。

示例模板文件(person.tmpl):

<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>Person Info</title>
</head>
<body><h1>Person Info</h1><p>Name: {{.Name}}</p><p>Age: {{.Age}}</p>
</body>
</html>

三、模板的解析与渲染

1. 解析模板文件

使用template.ParseFilestemplate.Parse方法解析模板文件或模板字符串,生成模板对象。

示例代码:

package mainimport ("html/template""os"
)type Person struct {Name stringAge  int
}func main() {// 解析模板文件tmpl, err := template.ParseFiles("./person.tmpl")if err != nil {panic(err)}// 创建数据data := Person{Name: "John Doe", Age: 30}// 执行模板渲染err = tmpl.Execute(os.Stdout, data)if err != nil {panic(err)}
}

运行上述代码,将会在终端上看到如下输出:
在这里插入图片描述

2. 模版渲染及输出方式

在渲染时候需要传递一个参数,用于指定输出到何处,常见的有4种目的地:

▷ 输出到文件
▷ 输出到变量
▷ 输出到屏幕
▷ 输出到页面

(1)输出到文件
package mainimport ("html/template""log""os"
)type Person9 struct {Name    stringAge     intHobbies []string
}func main() {tmplStr := `  
<!DOCTYPE html>  
<html>  
<head>  <meta charset="UTF-8">  <title>Person Info</title>  
</head>  
<body>  <h1>Person Info</h1>  <p>Name: {{.Name}}</p>  <p>Age: {{.Age}}</p>  <ul>  {{range .Hobbies}}  <li>{{.}}</li>  {{end}}  </ul>  
</body>  
</html>  
`// 创建一个模板对象,并解析模板字符串tmpl, err := template.New("personTmpl").Parse(tmplStr)if err != nil {log.Fatalf("Error parsing template: %v", err)}// 创建一个Person实例,并填充数据p := Person9{Name:    "John Doe",Age:     30,Hobbies: []string{"Reading", "Hiking", "Cooking"},}// 打开一个文件用于写入生成的HTML内容file, err := os.Create("person_info.html")if err != nil {log.Fatalf("Error creating file: %v", err)}defer file.Close()// 将模板应用到数据,并将结果写入文件err = tmpl.Execute(file, p)if err != nil {log.Fatalf("Error executing template: %v", err)}log.Println("HTML file generated successfully: person_info.html")
}

查看输出的文件
在这里插入图片描述

(2)输出到变量
var buf bytes.Bufferif err := tmpl.Execute(&buf, foo); err != nil {log.Fatalln(err)
}
fmt.Println(buf.String())
(3)输出到屏幕

下方各个案例都是输出到屏幕

(4)输出到页面
// http_server.go
package mainimport ("fmt""html/template""net/http"
)type User struct {Name stringAge  int
}// 定义发送接收数据函数
// 通过请求,进入页面(路由)  temp.Execute(resp, data)
// 通过URl进入某个页面
func findAll(resp http.ResponseWriter, req *http.Request) {// 接收到前端的信息 /findAll, 查询全部用户//使用map模拟用户userMap := make(map[int]User)userMap[1] = User{"jigntian", 1}userMap[2] = User{"xiaoming", 2}// 返回给前端页面并渲染上去// func ParseFiles(filenames ...string) (*Template, error)temp, _ := template.ParseFiles("./userlist.html")data := make(map[string]map[int]User)data["data"] = userMap//func (t *Template) Execute(wr io.Writer, data any) error// 输出到页面 第一个参数是 http.ResponseWriter 第二个参数是数据err := temp.Execute(resp, data)if err != nil {return}
}func main() {// HandleFunc http请求的处理函数// http程序启动之后是不会停止的,一直监听请求// 访问这个url就会触发 helloHandler 函数 (Request) ResponseWriter// func HandleFunc(pattern string, handler func(ResponseWriter, *Request))//第一个参数是请求路径,第二个参数是一个函数http.HandleFunc("/findAll", findAll)fmt.Println("Starting server at :8080")// func ListenAndServe(addr string, handler Handler) error// ListenAndServe监听TCP地址addr,并且会使用handler参数调用Serve函数处理接收到的连接。handler参数一般会设为nil,此时会使用DefaultServeMux。//如果用户自定义实现了Handler,那么根据相应路径在map中查询到相对应的Handler,然后再调用用户自定义的ServeHTTP处理请求。//如果用户没有自定义Handler,只注册了对应处理函数(使用了http.HandleFunc),那么就会根据默认DefaultServeMux去map查询到这个函数类型Handler,然后再调用ServeHTTP处理函数。// 开启监听程序的代码是放在main方法的最后一行的。if err := http.ListenAndServe("127.0.0.1:8080", nil); err != nil {fmt.Println("Error starting server:", err)}
}

userlist.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>查询用户</title>
</head>
<body>
<!--获取后端的数据 {{.data}}
遍历
{{range $k,$v := .data}}{{end}}-->{{range $k,$v := .data}}{{$k}}{{if eq $k 1}}{{.Name}}{{$v}}{{end}}
{{end}}</body>
</html>

运行服务器,浏览器访问
在这里插入图片描述

3. 从字符串载入模板

除了从文件载入模板,还可以从字符串载入模板。

示例代码:

package mainimport ("html/template""os"
)type Person struct {Name stringAge  int
}func main() {// 定义模板字符串tmplStr := `
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>Person Info</title>
</head>
<body><h1>Person Info</h1><p>Name: {{.Name}}</p><p>Age: {{.Age}}</p>
</body>
</html>
`// 解析模板字符串tmpl, err := template.New("person").Parse(tmplStr)if err != nil {panic(err)}// 创建数据data := Person{Name: "John Doe", Age: 30}// 执行模板渲染err = tmpl.Execute(os.Stdout, data)if err != nil {panic(err)}
}

在这里插入图片描述

四、模板语法

Go语言的模板语法简单而强大,支持变量、管道、条件判断、循环等控制结构。

1. 变量

使用{{.}}表示当前数据对象,使用{{$var := .}}可以定义一个变量,并在模板中通过$var引用它。

示例代码:

package mainimport ("html/template""os"
)type Person struct {Name stringAge  int
}func main() {tmplStr := `
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>Person Info</title>
</head>
<body><h1>Person Info</h1>{{$name := .Name}}<p>Name: {{$name}}</p><p>Age: {{.Age}}</p>
</body>
</html>
`tmpl, err := template.New("person").Parse(tmplStr)if err != nil {panic(err)}data := Person{Name: "John Doe", Age: 30}err = tmpl.Execute(os.Stdout, data)if err != nil {panic(err)}
}

在这里插入图片描述

2. 注释

在模板中,可以使用{{/* 注释内容 */}}来添加注释。

package main  import (  "fmt"  "html/template"  
)  func main() {  // 定义模板字符串  tmplStr := `  
<p>Name: {{.Name}}</p>  
<!-- 这是一个注释 -->  
<p>Age: {{.Age}}</p>  
{{/* 这也是一个注释 */}}  
`  // 解析模板字符串(省略了其他部分)  // ...  // 创建数据(省略了其他部分)  // ...  // 执行模板渲染(省略了其他部分)  // ...  
}

3. 管道

管道符号|用于将前一个命令的输出作为后一个命令的输入。

示例代码:

package mainimport ("html/template""os""strings"
)type Person4 struct {Name stringAge  int
}func main() {tmplStr := `  
<!DOCTYPE html>  
<html>  
<head>  <meta charset="UTF-8">  <title>Person Info</title>  
</head>  
<body><h1>Person Info</h1>  <p>Name: {{.Name | ToUpper}}</p>  {{/* 这里将我们定义的过滤器应用 */}}  <p>Age: {{.Age}}</p>  
</body>  
</html>  
`// 注册自定义函数funcMap := template.FuncMap{"ToUpper": strings.ToUpper,}// 将我们定义的函数应用于字符串解析tmpl, err := template.New("person").Funcs(funcMap).Parse(tmplStr)if err != nil {panic(err)}data := Person4{Name: "John Doe", Age: 30}err = tmpl.Execute(os.Stdout, data)if err != nil {panic(err)}
}

可见名字变成了大写
在这里插入图片描述

4. 条件判断

在模板中,可以使用{{if …}} {{else if…}} {{else}} {{end}}来进行条件判断。
模板if常见操作符
• not 非{{if not .condition}} {{end}}
• and 与{{if and .condition1 .condition2}} {{end}}
• or 或{{if or .condition1 .condition2}} {{end}}
• eq 等于{{if eq .var1 .var2}} {{end}}
• ne 不等于{{if ne .var1 .var2}} {{end}}
• lt 小于 (less than){{if lt .var1 .var2}} {{end}}
• le 小于等于{{if le .var1 .var2}} {{end}}
• gt 大于{{if gt .var1 .var2}} {{end}}
• ge 大于等于{{if ge .var1 .var2}} {{end}}

示例代码:

package mainimport ("html/template""os"
)type Person6 struct {Name stringAge  int
}func main() {tmplStr := `  
<!DOCTYPE html>  
<html>  
<head>  <meta charset="UTF-8">  <title>Person Info</title>  
</head>  
<body>  <h1>Person Info</h1>  <p>Name: {{.Name}}</p>  <p>Age: {{.Age}}</p>  {{if lt .Age  18}}  <p>This person is a boy.</p>  {{else if  gt .Age 60 }}  <p>This person is not an old man.</p> {{else}}<p>This person is not an adult.</p>{{end}}  
</body>  
</html>  
`tmpl, err := template.New("person6").Parse(tmplStr)if err != nil {panic(err)}data := Person6{Name: "John Doe", Age: 70}err = tmpl.Execute(os.Stdout, data)if err != nil {panic(err)}
}

在这里插入图片描述

5. 循环

在模板中,可以使用{{range …}} {{end}}来进行循环。

示例代码:

package mainimport ("html/template""os"
)type Person7 struct {Name stringAge  int
}type People8 struct {List []Person7
}func main() {// 定义模板字符串tmplStr := `  
<ul>  
{{range .List}}  <li>Name: {{.Name}}, Age: {{.Age}}</li>  
{{end}}  
</ul>  
`tmpl, err := template.New("person").Parse(tmplStr)if err != nil {panic(err)}// 创建数据data := People8{List: []Person7{{Name: "jingtian", Age: 25},{Name: "John Doe", Age: 30},{Name: "Jane Smith", Age: 25},},}err = tmpl.Execute(os.Stdout, data)if err != nil {panic(err)}
}

在这里插入图片描述


http://www.ppmy.cn/server/133337.html

相关文章

Vue Google 广告的配置

前置条件&#xff1a;已经在Google AdSense 中 添加网站 并通过审核 同时已创建广告单元。 因 VUE 的 Script 配置问题&#xff0c;所以不能直接拷贝内容。 index.html 配置 添加 Google 广告的脚本。 //index.template.html /* * 在head标签中添加 script 【 **** 】&#…

【Docker】Harbor 私有仓库和管理

目录 一、搭建本地私有仓库 二、harbor简介&#xff08;特性、构成、架构的数据流向&#xff09; 2.1 什么是Harbor 2.2 Harbor的特性 2.3 Harbor的构成 2.4 Harbor的工作原理&#xff08;运行流程&#xff09; 三、harbor部署以及配置文件 1. 部署 Docker-Compose 服…

React中的useState和useEffect解析

一、组件状态管理——useState 1.定义 useState 是一个 React Hook&#xff08;函数&#xff09;&#xff0c;它允许我们向组件添加一个状态变量&#xff0c;从而控制影响组件的渲染结果 和普通JS变量不同的是&#xff0c;状态变量一旦发生变化组件的视图UI也会跟着变化&…

STM32F1+HAL库+FreeTOTS学习17——事件标志组

STM32F1HAL库FreeTOTS学习17——事件标志组 1. 事件标志组1.1 事件标志组的的引入1.2 事件标志组简介1.3 事件标志组与队列、信号量的区别 2. 事件标志组下相关API函数2. 1 xEventGroupCreate()2. 2 xEventGroupCreateStatic()2. 3 vEventGroupDelete()2. 4 xEventGroupWaitBit…

python 爬虫 入门 三、登录以及代理。

目录 一、登录 &#xff08;一&#xff09;、登录4399 1.直接使用Cookie 2.使用账号密码进行登录 可选观看内容&#xff0c;使用python对密码进行加密&#xff08;无结果代码&#xff0c;只有过程分析&#xff09; 二、代理 免费代理 后续&#xff1a;协程&#xff0c;…

fastjson注解说明,fastjson注解有那些?fastjson是java的json序列化和反序列化工具包

fastjson注解说明,fastjson注解有那些?fastjson是java的json序列化和反序列化工具包 包版本说明 fastjson请使用1.2.83以上版本,小于这个版本的存在漏洞。 fastjson请使用1.2.83以上版本,小于这个版本的存在漏洞。 fastjson请使用1.2.83以上版本,小于这个版本的存在漏洞…

Golang Map简介

Go Map Map 简介 在Go语言中提供了map数据结构来存储键值对数据。map的数据类型为map[K]V&#xff0c;其中K为键的类型&#xff0c;V为值的类型。map的键类型必须支持操作符&#xff0c;用来比较两个键是否相等。Go语言提供了4种内置的map操作: len、delete、comparison、ass…

关于C语言——对一个数据定义的两种属性

对一个数据的定义&#xff0c;需要去定义它的两种属性:数据类型和存储类型。 对于数据类型主要有: intcharlongfloatdouble 对于存储类型有这四种: auto static register extern 平时使用的时候一般不标明存储类型&#xff0c;而存储类型主动是为auto&#xff0c;自动变…