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

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
	}
}

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于node.js和Vue3的医院挂号就诊住院信息管理系统

摘要&#xff1a; 随着信息技术的快速发展&#xff0c;医院挂号就诊住院信息管理系统的构建变得尤为重要。该系统旨在提供一个高效、便捷的医疗服务平台&#xff0c;以改善患者就医体验和提高医院工作效率。本系统基于Node.js后端技术和Vue3前端框架进行开发&#xff0c;利用其…

“趣味夕阳,乐享生活”小组活动(第二节)

立冬以来&#xff0c;天气日渐寒冷&#xff0c;气温变化较大&#xff0c;各种传染病多发&#xff0c;为进一步增强老年人冬季预防传染病保健意识及科学合理健康的生活方式。近日&#xff0c;1月22日&#xff0c;南阳市人人社工灌涨站开展了“趣味夕阳&#xff0c;乐享生活”小组…

Maps基础知识

什么是Maps&#xff1f; 在JavaScript中&#xff0c;Map是一种用于存储键值对的数据结构。它类似于对象&#xff0c;但有一些区别。 Map对象允许任何类型的值作为键&#xff08;包括对象、函数和基本数据类型&#xff09;&#xff0c;而对象只能使用字符串或符号作为键。这使得…

Python - SnowNLP 情感分析与自定义训练

目录 一.引言 二.SnowNLP 情感分析 1.安装 SnowNLP 2.测试 SnowNLP 三.SnowNLP 自定义训练 1.数据集准备 2.训练与保存 3.模型替换 4.模型测试 5.SnowNLP 原理 ◆ Bayes 公式 ◆ 先验概率 ◆ 后验概率 ◆ 情感模型 四.总结 一.引言 SnowNLP 是一个基于 Python …

Chrome 插件调试

http://blog.haoji.me/chrome-plugin-develop.html#te-bie-zhu-yi-background-de-bao-cuo 手把手&#xff1a;Chrome浏览器开发系列(四)&#xff1a;调试我们开发的插件 - 掘金

5_机械臂运动学基础_矩阵

上次说的向量空间是为矩阵服务的。 1、学科回顾 从科技实践中来的数学问题无非分为两类&#xff1a;一类是线性问题&#xff0c;一类是非线性问题。线性问题是研究最久、理论最完善的&#xff1b;而非线性问题则可以在一定基础上转化为线性问题求解。 线性变换&#xff1a; 数域…

第12章_集合框架(Collection接口,Iterator接口,List,Set,Map,Collections工具类)

文章目录 第12章_集合框架本章专题与脉络1. 集合框架概述1.1 生活中的容器1.2 数组的特点与弊端1.3 Java集合框架体系1.4 集合的使用场景 2. Collection接口及方法2.1 添加2.2 判断2.3 删除2.4 其它 3. Iterator(迭代器)接口3.1 Iterator接口3.2 迭代器的执行原理3.3 foreach循…

基于 pytorch-openpose 实现 “多目标” 人体姿态估计

前言 还记得上次通过 MediaPipe 估计人体姿态关键点驱动 3D 角色模型&#xff0c;虽然节省了动作 K 帧时间&#xff0c;但是网上还有一种似乎更方便的方法。MagicAnimate 就是其一&#xff0c;说是只要提供一张人物图片和一段动作视频 (舞蹈武术等)&#xff0c;就可以完成图片…

【模拟】力扣1576(Java)

题目 class Solution {public String modifyString(String ss){char[] s ss.toCharArray();int n s.length;for(int i0;i<n;i){if(s[i] ?){for(char cha;ch<z;ch){if((i 0 || ch!s[i-1])&&(i n-1 || ch! s[i1])){s[i] ch;break;}}}}return String.valu…

forEach()方法跳出循环

forEach方法如何跳出循环_foreach跳出循环-CSDN博客 forEach方法遍历数组&#xff0c;每次遍历都根据条件判断&#xff0c;当条件符合时&#xff0c;就跳出整个遍历&#xff0c;不再继续遍历后面的元素 forEach()方法跳出整个循环遍历 forEach方法一般用抛出异常的方式跳出整…

原生图数据库实现原理解析

目录 前言1 实现原理&#xff1a;免索引邻接1.1 免索引邻接构建1.2 查询性能保障 2. 物理存储实现2.1 节点存储文件2.2 关系边存储文件2.3 属性数据的存储处理 3. RDF图模型和属性图模型的比较3.1 RDF图模型3.2 属性图模型 4. 查询语言比较4.1. SPARQL4.2 Cypher4.3 Gremlin4.4…

摄像机视角的切换_unity基础开发教程

摄像机视角的切换 前言一、场景搭建二、脚本编辑三、脚本挂载四、运行效果结语 前言 我们在游戏中经常可以看到游戏视角的切换&#xff0c;今天我们就做一个视角切换的小demo&#xff0c;学会之后可以将其融入到自己的游戏制作当中。 话不多说&#xff0c;我们现在开始&#xf…

Unity中实现合理塔防寻路机制

前言 在一款TD游戏中,最重要的单位就两大类:防御塔(Tower)和敌人单位(Enemy)。在处理敌人单位的AI行为时,最基本也是最重要的就是自动寻路。在各式TD游戏中,防御塔的攻击方式以及敌人单位的Buff机制往往是能做出差异化的地方;而在寻路问题上,几乎是没有差异的,面对…

如何使用docker实现越权漏洞-webug靶场搭建(超详解)

越权漏洞-webug靶场搭建 1.打开docker systemctl start docker 2.查找webug docker search webug 3.拉取docker.io/area39/webug 镜像 docker pull docker.io/area39/webug 4.查看镜像 docker images 5.创建容器 docker run -d -p 8080:80 --name webug docker.io/area39/we…

Python 第四十三章 MYSQL 补充

多表查询 1.笛卡尔积:将两表所有的数据一一对应,生成一张大表 select * from dep,emp; #两个表拼一起 select * from dep,emp where dep.id emp.dep_id; #找到两表之间对应的关系记录 select * from dep,emp where dep.id emp.dep_id and dep.name技术; #筛选部门名称为技…

Sulfo Cy2 Biotin,水溶性 Cy2 生物素,能够与各种氨基基团特异性结合

您好&#xff0c;欢迎来到新研之家 文章关键词&#xff1a;Sulfo Cyanine2 Biotin&#xff0c;Sulfo Cy2 Biotin&#xff0c;水溶性 Cy2 生物素&#xff0c;Sulfo-Cy2-Biotin&#xff0c;水溶性-Cy2-生物素 一、基本信息 产品简介&#xff1a;Sulfo Cyanine2 Biotin, also k…

npm安装卡住问题(最新版)

npm安装卡住问题(最新版) 背景&#xff1a; ​ 最近这两天用npm安装一些包的时候&#xff0c;发现一直卡住&#xff1a; 报错&#xff1a; idealTree:npm: sill idealTree buildDeps之前能用的现在不能用了&#xff0c;我一想&#xff0c;是不是源头的问题&#xff0c;还真是…

安全防御第二次作业

将内网中各个接口能够ping通自己的网关 1.划分vlan [sw6]vlan batch 2 3 [sw6]int g0/0/2 [sw6-GigabitEthernet0/0/2]port link-type access [sw6-GigabitEthernet0/0/2]port default vlan 2 [sw6-GigabitEthernet0/0/2]int g0/0/3 [sw6-GigabitEthernet0/0/3]port link-t…

JVM/GC复习1---更新中

JVM/GC JVMGC垃圾回收算法1.引用计数法2.标记清除发3.标记压缩算法4.复制算法5.分代算法 收集器1.串行垃圾收集器2.并行垃圾收集器2.CMS垃圾收集器 3.G1垃圾收集器(重点)jdk1.7开始1.9默认的回收器Young GC模式Mixed GCFull GC JVM 待更新中ing GC 垃圾回收:程序运行的时候必…

leetcode刷题(剑指offer) 105.从前序与中序遍历序列构造二叉树

105.从前序与中序遍历序列构造二叉树 给定两个整数数组 preorder 和 inorder &#xff0c;其中 preorder 是二叉树的先序遍历&#xff0c; inorder 是同一棵树的中序遍历&#xff0c;请构造二叉树并返回其根节点。 示例 1: 输入: preorder [3,9,20,15,7], inorder [9,3,15,…