目录
第一节-go模板语法详解
go模板的基本用法
1.定义模板
2.解析模板
3.渲染模板
每次使用的时候都将这三部分先写上,根据顺序一步一步进行。遇事不决,先写注释
下面是一个基础代码展示
DemoB02.go代码部分
package main
import (
"fmt"
"html/template"
"net/http"
)
// User 结构体用于表示用户信息
type User struct {
Name string // 用户名
Age int // 年龄
Gender string // 性别
}
// sayHello 是处理 HTTP 请求的处理器函数
func sayHello(w http.ResponseWriter, r *http.Request) {
// 定义模板文件路径
// 2.解析模板文件
t, err := template.ParseFiles("D:\\Golang\\gin_demo\\Unit02\\demoB02.html")
if err != nil {
// 如果解析模板文件失败,打印错误信息
fmt.Println("ParseFiles err:", err)
return
}
// 利用结构体定义用户信息
u1 := User{
Name: "VON",
Age: 18,
Gender: "男",
}
// 利用 map 定义用户信息
m1 := map[string]interface{}{
"name": "清洒",
"age": 18,
"gender": "男",
}
// 定义学生姓名列表
nameList := []string{
"小明",
"小红",
"小刚",
}
// 3.渲染模板并将数据传递给模板
t.Execute(w, map[string]interface{}{
"u1": u1, // 传递结构体用户信息
"m1": m1, // 传递 map 用户信息
"name": nameList, // 传递学生姓名列表
})
}
func main() {
// 绑定路由,将根路径 "/" 的请求交给 sayHello 处理
http.HandleFunc("/", sayHello)
// 监听并启动 HTTP 服务器,监听 8080 端口
err := http.ListenAndServe(":8080", nil)
if err != nil {
// 如果启动服务器失败,打印错误信息并退出程序
fmt.Println("ListenAndServe: ", err)
return
}
}
DemoB02.html代码部分
<!-- 1. 构建模版 -->
<!-- 这是一个简单的 HTML 模板文件,用于生成动态内容。 -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!-- 使用 Go 模板语法 {{ . }} 来插入传递给模板的数据。 -->
<p>u1</p>
<p>{{ .u1.Name}}</p>
<p>{{ .u1.Age}}</p>
<p>{{ .u1.Gender}}</p>
<p>m1</p>
<p>{{ .m1.name}}</p>
<p>{{ .m1.age}}</p>
<p>{{ .m1.gender}}</p>
<!-- 条件语句-->
<hr>
<!-- 定义变量 $v1 并赋值为 1 -->
{{ $v1 := 1 }}
<!-- 检查 $v1 是否等于 1 -->
{{ if eq $v1 1 }}
<p>v1 == 1</p>
{{ else }}
<p>v1 != 1</p>
{{ end }}
<!-- 检查 $v1 是否小于 1 -->
{{ if lt $v1 1 }}
<p>v1 < 1</p>
{{ else }}
<p>v1 >= 1</p>
{{ end }}
<!-- 检查 $v1 是否大于 1 -->
{{ if gt $v1 1 }}
<p>v1 > 1</p>
{{ else }}
<p>v1 <= 1</p>
{{ end }}
<hr>
<!--range的应用-->
{{ range $id,$name := .name }}
<p>{{ $id }} - {{ $name }}</p>
{{ end }}
<!--with的应用-->
<hr>
{{ with .u1 }}
<p>{{ .Name}}</p>
<p>{{ .Age}}</p>
<p>{{ .Gender}}</p>
{{ end }}
</body>
</html>
效果展示
第二节-模板嵌套
这一部分不知道为什么我的路径只能选用绝对路径,相对路径会找不到文件位置。
具体每部分都有相应的注释,可以参考注释来进行理解。
main.go
package main
import (
"fmt"
"html/template"
"net/http"
)
// f1 处理函数,用于处理根路径请求
func f1(w http.ResponseWriter, r *http.Request) {
// 自定义函数,用于在模板中调用
k := func(name string) (string, error) {
return name + "真帅", nil
}
// 创建一个新的模板对象
t := template.New("demoB01.html")
// 应用自定义函数到模板
t.Funcs(template.FuncMap{
"kua": k,
})
// 解析模板文件
t, err := t.ParseFiles("D:\\Golang\\gin_demo\\Unit02\\demoB01.html")
if err != nil {
// 如果解析模板文件失败,返回内部服务器错误
http.Error(w, fmt.Sprintf("解析模板文件失败: %v", err), http.StatusInternalServerError)
return
}
// 渲染模板文件
name := "VON"
if err := t.Execute(w, name); err != nil {
// 如果渲染模板文件失败,返回内部服务器错误
http.Error(w, fmt.Sprintf("渲染模板文件失败: %v", err), http.StatusInternalServerError)
}
}
// demo01 处理函数,用于处理 /texthtml 路径请求
func demo01(w http.ResponseWriter, r *http.Request) {
// 解析多个模板文件,父模板写在前面,子模板写在后面
t, err := template.ParseFiles("D:\\Golang\\gin_demo\\Unit03\\demoB01.html", "D:\\Golang\\gin_demo\\Unit03\\ul.html")
if err != nil {
// 如果解析模板文件失败,打印错误信息并返回
fmt.Println("解析模板失败:", err)
return
}
// 渲染模板文件
name := "清洒"
if err := t.Execute(w, name); err != nil {
// 如果渲染模板文件失败,返回内部服务器错误
http.Error(w, fmt.Sprintf("渲染模板文件失败: %v", err), http.StatusInternalServerError)
}
}
// main 函数,程序入口
func main() {
// 注册处理函数
http.HandleFunc("/", f1)
http.HandleFunc("/texthtml", demo01)
// 启动 HTTP 服务器,监听 1209 端口
err := http.ListenAndServe(":1209", nil)
if err != nil {
// 如果启动服务器失败,打印错误信息并返回
fmt.Println("启动服务器失败:", err)
return
}
}
ul.html
<ul>
<li>一</li>
<li>二</li>
<li>三</li>
</ul>
效果展示
第三节-模板继承
在做网页的时候难免会有相同的地方,如果每次使用都重新写一次,会大大影响性能,也会影响运行效率,因此对于公共部分我们可以采用继承的方式来进行优化。以下是一个简单的例子。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>模板继承</title>
<!-- 添加全局样式 -->
<style>
/* 重置所有元素的内外边距 */
* {
margin: 0;
padding: 0;
}
/* 导航栏样式 */
.nav {
height: 50px; /* 高度为 50px */
width: 100%; /* 宽度为 100% */
position: fixed; /* 固定定位 */
top: 0; /* 距离顶部 0px */
background-color: #d4127c; /* 背景颜色 */
}
/* 主体内容区域样式 */
.main {
margin-top: 50px; /* 顶部外边距为 50px,以避免被导航栏遮挡 */
}
/* 菜单栏样式 */
.menu {
width: 20%; /* 宽度为 20% */
height: 100%; /* 高度为 100% */
position: fixed; /* 固定定位 */
left: 0; /* 距离左侧 0px */
background-color: #124fd4; /* 背景颜色 */
}
/* 中心内容区域样式 */
.center {
text-align: center; /* 文本居中对齐 */
}
</style>
</head>
<body>
<!-- 导航栏 -->
<div class="nav"></div>
<!-- 主体内容区域 -->
<div class="main">
<!-- 菜单栏 -->
<div class="menu"></div>
<!-- 中心内容区域 -->
<div class="content center">
{{block "content" .}}{{end}} <!-- 这里是子模板插入内容的地方 -->
</div>
</div>
</body>
</html>
上述代码是网页中通用的样式
不难看出这两部分就内容区域不同,因此可以将相同部分进行封装。
将需要填充内容的部分给留出来。
home2.html
这个地方的“.”千万不能省略,我就是省略了这个地方的“.”导致找了好久的问题
index2.html
目录部分展示
注意事项
这里以home2函数为例,main.go部分代码展示,大致步骤相似,还是三步走,上述标注的地方适当的注意一下。
第四节-模板补充
为了防止与前端一些用法上面发生冲突,有时候自定义模板就显得格外重要。
下面是一个小例子
前端页面就可以使用到我们自定义的模板了。
效果图