【JSON2WEB】03 go的模板包html/template的使用

news2024/9/24 13:23:12

Go text/template 是 Go 语言标准库中的一个模板引擎,用于生成文本输出。它使用类似于 HTML 的模板语言,可以将数据和模板结合起来,生成最终的文本输出。

Go html/template包实现了数据驱动的模板,用于生成可防止代码注入的安全的HTML内容。
它提供了和text/template包相同的接口,Go语言中输出HTML的场景都应使用html/template这个包。

1 使用方法

html/template 为go的内置包直接 import “html/template” 即可,模板引擎的使用一般三个步骤,定义,解析,渲染。
模板语法都包含在 {{和}} 中间,其中 {{.}} 中的点表示当前对象。对象可以是变量、内置变量、控制结构、内部函数、自定义函数,注释等等。

2 从Hello World开始

2.1 创建一个html模板文件

模板文件名为 hello,html,内容如下:

{{.}}

在这里插入图片描述

2.2 解析模板并输出到浏览器

// test3 project main.go
package main

import (
	"net/http"
	"html/template"
)

func main() {
	http.HandleFunc("/", hello)
	println("打开浏览器试试 http://localhost:5217")
	err := http.ListenAndServe(":5217", nil)
	if err != nil {
		println("HTTP server start failed! err : ", err)
		return
	}
}

// hello 函数把解析后的文件输出到html
func hello(w http.ResponseWriter, r *http.Request) {
	s := "Hello World!"
	t, _ := template.ParseFiles("hello.html")
	t.Execute(w, s)
}

运行一下:
在这里插入图片描述

浏览器查看:
在这里插入图片描述
是不是很简单啊。

3 一个综合使用的例子

这个例子包括解析结构体,map,内置变量,注释,内置函数,自定义函数等。

3.1 创建一个html模板

其实文件名叫啥都是,比如html.tmpl

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>golang html demo</title>
</head>
<body>
    <div>
      <p>王子:</p>
        <p>Hello {{.m1.name}}</p>
        <p>年龄: {{.m1.age}}</p>
        <p>性别: {{.m1.gender}}</p>
          
      <p>公主:</p>
      {{/* with 省略写法 */}}
      {{with .u1}}
        <p>Hello {{ .Name}}</p>
        <p>年龄: {{ .Age}}</p>
        <p>性别: {{ .Gender}}</p>
      {{end}}
    </div>
    <div>
     <p>内置变量:</p>
      {{/* 定义内置变量*/}}
      {{$i := 100}}
      {{$x := .u1.Age}}
      {{/* 在页面显示内置变量*/}}
      {{$i}}
      {{$x}}
    </div>
    
    <div>
      <p>内置函数:</p>
      {{/*内置函数*/}}
      {{$a := 0}}
      {{$b := 1}}
      {{or $a $b}}
      {{and $a $b}}
      {{len .m1}}
      
      <p>比较运算:</p>
      {{eq $a $b}}
    </div>
        
</body>
</html>

3.2 Go代码

// 模板只能传入一个变量,多个变量需要组合到 map里

package main

import (
	"fmt"
	"html/template"
	"net/http"
)

type User struct {
	Name   string
	Gender string
	Age    int
}

func index(w http.ResponseWriter, r *http.Request) {
	// 解析模板
	t, err := template.ParseFiles("html.tmpl")
	if err != nil {
		fmt.Println("Parse template failed! err:", err)
		return
	}
	// 渲染模板
	u1 := User{
		Name:   "小公主",
		Gender: "女",
		Age:    16,
	}
	m1 := map[string]interface{}{
		"name":   "小皇子",
		"gender": "男",
		"age":    18,
	}
	err = t.Execute(w, map[string]interface{}{
		"u1": u1,
		"m1": m1,
	})
	if err != nil {
		fmt.Println("render template failed,err : ", err)
		return
	}

}

func diyifun(w http.ResponseWriter, r *http.Request) {
	// 自定义函数
	// 1 自定义函数变量
	wenfun := func(name string) (string, error) {
		return name + " 您今儿吃了吗?", nil
	}
	// 2 创建一个名称为diyfun的模板对象,要求名称跟文件名一样,扩展名也是
	t := template.New("diyfun.tmpl")
	// 3 在解析模板之前注册函数
	t.Funcs(template.FuncMap{
		"wen": wenfun,
	})
	// 4 解析模板
	_, err := t.ParseFiles("diyfun.tmpl")
	if err != nil {
		fmt.Println("Parsetemplate failed! err:", err)
		return
	}
	// 渲染模板
	t.Execute(w, "白龙马")
}

func main() {
	http.HandleFunc("/index", index)
	http.HandleFunc("/diyifun", diyifun)
	println("打开浏览器试试 http://localhost:5217/index")
	err := http.ListenAndServe(":5217", nil)
	if err != nil {
		fmt.Println("HTTP server start failed! err : ", err)
		return
	}
}

3.3 打开浏览器看渲染效果

  • index 综合
    在这里插入图片描述

  • diyifun 自定义函数
    在这里插入图片描述

4 更复杂的嵌套模板

就是在一个模板中嵌套另外的一个模板。
在需要嵌套的地方
{{ template 模板名 . }}
其中,这个 . 是在模板中传递数据用的

4.1 先看看模板

  • Home.tmpl
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <title>嵌套2个子模板</title>
</head>
<body>
	<p>这是子模板1:</p>
    ul :<br>
    {{ template "tmp1.tmpl" . }}
    <hr>
    <p>这是子模板1:</p>
    ol :<br>
    {{ template "tmp2.tmpl" . }}
</body>
</html>
  • tmp1.tmpl
<ul>
    <li>{{ .name }}</li>
    <li>{{ .sex }}</li>
</ul>

  • tmp2.tmpl
<ol>
    <li>{{ .name }}</li>
    <li>{{ .sex }}</li>
</ol>

4.2 主控程序

// test3 project main.go
package main

import (
	"fmt"
	"html/template"
	"net/http"
)

func main() {
	http.HandleFunc("/home", home)
	println("打开浏览器试试 http://localhost:5217/home")
	err := http.ListenAndServe(":5217", nil)
	if err != nil {
		println("HTTP server start failed! err : ", err)
		return
	}
}

// hello 函数把解析后的文件输出到html
func home(w http.ResponseWriter, r *http.Request) {
	//	s := "Hello World!"
	t, err := template.ParseFiles("home.tmpl", "tmp1.tmpl", "tmp2.tmpl")
	if err != nil {
		fmt.Printf("parse file failed err := %v", err)
	}

	mp := map[string]interface{}{
		"name": "白龙马",
		"sex":  "男",
	}
	err = t.Execute(w, mp)
	if err != nil {
		fmt.Printf("execute file failed err := %v", err)
	}
}

4.3 运行效果

在这里插入图片描述

5 block定义一个默认模板

Home.tmpl 修改一下,嵌入一个不存在的模板tmp3.tmpl,如果直接 {{ template “tmp3.tmpl” . }}嵌入编译时就会报错,用block定义一个默认模板就OK:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <title>嵌套2个子模板</title>
</head>
<body>
	<p>这是子模板1:</p>
    ul :<br>
    {{ template "tmp1.tmpl" . }}

    <hr>
    
    <p>这是子模板2:</p>
    ol :<br>
    {{ template "tmp2.tmpl" . }}

    <hr>

    <p>这是子模板3:</p>
    default :<br>
    {{ block "tmp3.tmpl" . }}
       tmp3.tmpl 没找到,这是默认模板的内容
    {{end}}


</body>
</html>

运行效果如下:
在这里插入图片描述
现在新建一个tmp3.tmpl的模板:

别搞错了,我才是Tmp3.tmpl
<br>
{{ .name}}
{{ .sex}}

模板解析采用统配符解析函数:
t, err := template.ParseGlob(“nest/*.tmpl”)

解析 nest目录下所有的*.tmpl文件
刷新一下浏览器,默认模板替换为了tml3.tmpl

在这里插入图片描述

6 还尝试了其它方法

比如条件渲染,循环结构等。

package main

import (
	"fmt"
	"html/template"
	"net/http"
)

type Book struct {
	Title     string
	Publisher string
	Year      int
}

func main() {

	http.HandleFunc("/index2", index2)

	err := http.ListenAndServe(":5217", nil)
	if err != nil {
		fmt.Println("HTTP server start failed! err : ", err)
		return
	}

}

func index2(w http.ResponseWriter, r *http.Request) {

	// // 解析模板
	// t, err := template.ParseFiles("index.html")
	// if err != nil {
	// 	fmt.Println("Parse template failed! err:", err)
	// 	return
	// }

	// 字符串
	t1 := template.New("Template")
	t1, _ = t1.Parse("External variable has the value [{{.}}]\n")
	t1.Execute(w, "Amazing")
	// 结构体
	b := Book{"The CSound Book", "MIT Press", 2002}
	t1.Execute(w, b)

	// 结构体字段
	t2 := template.New("Template")
	t2, _ = t2.Parse("External variable Book has the values [Title: {{.Title}}, Publisher: {{.Publisher}}, Year: {{.Year}}]\n")
	t2.Execute(w, b)

	// 内部变量 $前缀
	t, _ := template.New("Template").Parse("{{$var:=2150}}Internal variable has the value [{{$var}}]\n")
	t.Execute(w, nil)

	// 条件渲染
	/*
		等于 eq(对应 ==):

		非等于 ne(对应 !=)

		小于 lt(对应 <)

		小于等于 le(对应 <=)

		大于 gt(对应 >)

		大于等于 ge(对应 >=)
	*/
	t, err := template.New("Template").Parse("{{if eq . `filler`}}This is filler...{{else}}It's something else...{{end}}\n")
	if err != nil {
		panic(err)
	}
	t.Execute(w, "filler")

	// 直接写入布尔变量,而不是比较语句。
	t, _ = template.New("Template").Parse("{{if .}}This is true.{{else}}This is false.{{end}}\n")
	t.Execute(w, false)

	// 循环遍历
	computerList := []string{"Arduino", "Raspberri Pi", "NVidia Jetson Nano"}
	t, err = template.New("Template").Parse("My favorite computers are:\n{{range .}}{{.}}\n{{end}}\n")
	if err != nil {
		panic(err)
	}
	t.Execute(w, computerList)

	// 有序列表
	dishesList := []string{"Enciladas con Pollo", "Hot&Spicy Pizza", "Spaghetti Bolognese"}
	t, err = template.New("Template").Parse("My favorite dishes are:\n{{range $index, $item:=.}}{{$index}}) {{$item}}\n{{end}}\n")
	if err != nil {
		panic(err)
	}
	t.Execute(w, dishesList)

	// 模板中使用函数
	//dishesList := []string{"Enciladas con Pollo", "Hot&Spicy Pizza", "Spaghetti Bolognese"}
	t, err = template.New("Template").Funcs(template.FuncMap{"add": add}).Parse("My favorite dishes are:\n{{range $index, $item:=.}}{{add $index 1}}) {{$item}}\n{{end}}\n")
	if err != nil {
		panic(err)
	}
	t.Execute(w, dishesList)

	//dishesList := []string{"Enciladas con Pollo", "Hot&Spicy Pizza", "Spaghetti Bolognese"}
	tmpl := "Index{{dl}}Dish\n{{range $index, $item:=.}}{{add $index 1}}{{dl}}{{$item}}\n{{end}}\n"
	funcMap := template.FuncMap{"add": add, "dl": delimiter(",")}
	t, _ = template.New("Template").Funcs(funcMap).Parse(tmpl)
	t.Execute(w, dishesList)
}

// 模板中使用函数add
func add(a, b int) int {
	return a + b
}

// 这只分割符
func delimiter(s string) func() string {
	return func() string {
		return s
	}
}

运行结果:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1408962.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一文掌握Shell

文章目录 Shell概述脚本的常用执行方式Linux中的sh解释器Linux中的/etc 编写sh脚本第一个sh脚本变量1. 系统预定义变量2. 自定义变量3. 变量定义规则单引号和双引号的区别 4. 特殊变量 运算符命令替换条件判断常用判断语句 流程控制if语句case语句while循环 read读取控制台输入…

生产、计划、仓库、质量,一大堆的工厂数据要怎么收集?MES系统替你解决!

随着制造业的发展和进步&#xff0c;工厂运营面临着越来越多的挑战&#xff0c;特别是在数据管理和生产过程控制方面。生产、计划、仓库、质量等方面的数据分散在各个系统和部门中&#xff0c;数据的收集和分析变得复杂而困难。然而&#xff0c;MES系统为工厂提供了一个综合性解…

成功安装DCNv4

最终结果 终于安装成功了。 环境 系统&#xff1a;ubuntu22.04 CUDA&#xff1a;12.1 python&#xff1a;3.11 显卡驱动&#xff1a;545 安装过程 系统、CUDA和python的安装过程忽略&#xff0c;这些都能找到。这里只写不同的地方。 配置CUDAHOME 执行命令“ gedit ~/…

余弦定理是怎么推导的?

余弦定理是怎么推导的? 已知余弦定理(low of cosines)表达如下: A B 2 = B C 2 + A C 2 − 2 B C ∗ A C ∗ cos ⁡ θ AB^2=BC^2+AC^2-2BC*AC*\cos \theta AB2=BC2+AC2−2BC∗AC∗cosθ,其中 A B , B C , A C AB,BC,AC AB,BC,AC和 θ \theta θ的关系如下: 那么这个公式是…

数据库缓存策略

数据库缓存策略 以下是数据库与缓存的五种常见策略。 1缓存旁路 缓存旁路&#xff08;Cache-Aside&#xff09; 在缓存旁路策略中&#xff0c;数据库缓存位于数据库旁边。当应用程序请求数据时&#xff0c;它会首先检查缓存 如果缓存中存在数据&#xff08;缓存命中&#xff…

风速预测 | Python基于CEEMDAN-CNN-Transformer+ARIMA的风速时间序列预测

目录 效果一览基本介绍程序设计参考资料 效果一览 基本介绍 CEEMDAN-CNN-TransformerARIMA是一种用于风速时间序列预测的模型&#xff0c;结合了不同的技术和算法。收集风速时间序列数据&#xff0c;并确保数据的质量和完整性。这些数据通常包括风速的观测值和时间戳。CEEMDAN分…

SpringCloudAlibaba系列之Nacos实战

目录 注意事项 参考资源 Nacos配置中心 初始化项目 进行Nacos相关配置 运行 Nacos注册中心 dubbo方式 对外暴露接口dubbo-api 服务提供者dubbo-provider 服务消费者dubbo-consumer 负载均衡客户端方法 服务提供者 服务消费者 注意事项 不管是使用Nacos配置中心&…

使用POI生成word文档的table表格

文章目录 使用POI生成word文档的table表格1. 引入maven依赖2. 生成table的两种方式介绍2.1 生成一行一列的table2.2 生成固定行列的table2.3 table合并列2.4 创建多个table存在的问题 使用POI生成word文档的table表格 1. 引入maven依赖 <dependency><groupId>org.…

智能家居20年,从「动手」到「用脑」

【潮汐商业评论/原创】 正在装修新家的Carro最近陷入了纠结之中&#xff0c;“还没想好要怎么装一套完整的智能家居&#xff0c;家里的基装就已经开始了。” 事实上&#xff0c;Carro对智能家居也不了解&#xff0c;并不知道该如何下手&#xff0c;心想“要是能一次性设计好就…

鸿蒙常用UI效果及一些处理方式总结

前言&#xff1a; DevEco Studio版本&#xff1a;4.0.0.600 详细使用介绍 1、Text的一些常用设置 Text(this.message).fontSize(50)//字体大小.fontColor(Color.White)//字体颜色.fontWeight(FontWeight.Bold)//字体加粗.backgroundColor(Color.Black)//背景颜色.fontStyle(…

利用Python实现科学式占卜

一直以来,中式占卜都是基于算命先生手工实现,程序繁琐(往往需要沐浴、计算天时、静心等等流程)。准备工作复杂(通常需要铜钱等道具),计算方法复杂,需要纯手工计算二进制并转换为最终的卦象,为了解决这个问题,笔者基于python实现了一套科学算命工具,用于快速进行占卜…

IDEA导出jar

1、选择导出方式 2、选择Main Class 3、构建jar

数据结构与算法教程,数据结构C语言版教程!(第五部分、数组和广义表详解)七

第五部分、数组和广义表详解 数组和广义表&#xff0c;都用于存储逻辑关系为“一对一”的数据。 数组存储结构&#xff0c;99% 的编程语言都包含的存储结构&#xff0c;用于存储不可再分的单一数据&#xff1b;而广义表不同&#xff0c;它还可以存储子广义表。 本章重点从矩阵…

java复习篇 数据结构:链表第二节 哨兵

目录 单向链表哨兵 初始 头插 思路 代码 尾插 思路 遍历 遍历验证头插 尾插代码 尾插测试 get 思路 代码 测试 insert 思路 代码 测试 remove 移除头结点 提问 移除指定位置 测试 单向链表哨兵 单向链表里面有一个特殊的节点称为哨兵节点&#xff0c;…

[pytorch入门] 2. tensorboard

tensorboard简介 TensorBoard 是一组用于数据可视化的工具。它包含在流行的开源机器学习库 Tensorflow 中.但是也可以独立安装&#xff0c;服务Pytorch等其他的框架 可以常常用来观察训练过程中每一阶段如何输出的 安装pip install tensorboard启动tensorboard --logdir<d…

redis-发布缓存

一.redis的发布订阅 什么 是发布和订阅 Redis 发布订阅 (pub/sub) 是一种消息通信模式&#xff1a;发送者 (pub) 发送消息&#xff0c;订阅者 (sub) 接收消息。 Redis 客户端可以订阅任意数量的频道。 Redis的发布和订阅 客户端订阅频道发布的消息 频道发布消息 订阅者就可…

MATLAB知识点:mode :计算众数

​讲解视频&#xff1a;可以在bilibili搜索《MATLAB教程新手入门篇——数学建模清风主讲》。​ MATLAB教程新手入门篇&#xff08;数学建模清风主讲&#xff0c;适合零基础同学观看&#xff09;_哔哩哔哩_bilibili 节选自第3章 3.4.1节 mode &#xff1a;计算众数 众数是指一…

量子网络是什么

量子网络是基于量子力学规律对量子信息进行存储、处理和传输的物理装置&#xff0c;是实现量子通讯和大规模量子计算的基础。清华大学研究团队利用同种离子的双类型量子比特编码&#xff0c;在国际上首次实现无串扰的量子网络节点&#xff0c;对未来实现量子通讯和大规模量子计…

使用Linux SDK客户端向AWS Iot发送数据

参考链接&#xff1a; https://ap-southeast-1.console.aws.amazon.com/iot/home?regionap-southeast-1#/test 此篇文章用于测试&#xff0c;使用Linux SDK客户端向AWS Iot发送数据&#xff0c;准备环境如下&#xff1a; 1、客户端环境准备 1.1 客户端操作系统 虚拟机一台…

Docker中安装 RabbitMQ

1、下载 RabbitMQ 镜像 下载最新版本的镜像&#xff1a; docker pull rabbitmq更多版本的镜像可以访问 Docker 官网&#xff1a;https://hub.docker.com/_/rabbitmq?tabtags 2、创建并运行 RabbitMQ 容器 启动命令&#xff1a; docker run -d -p 15672:15672 -p 5672:567…