GO web学习(二)
跟着b站https://space.bilibili.com/361469957 杨旭老师学习做的笔记
Response响应
ResponseWriter
包括Writer,WriterHeader,Header
- 从服务器向客户端返回响应需要使用 ResponseWriter
- ResponseWriter 是一个接口,handler 用它来返回响应
- 真正支撑 ResponseWriter 的幕后 struct 是非导出的 http.response
// w http.ResponseWriter, r *http.Request
// 其实 w 也是个指针,按引用传递
写入到 ResponseWriter
- Write 方法接收一个 byte 切片作为参数,然后把它写入到 HTTP 响应的 Body 里面。
- 如果在 Write 方法被调用时,header 里面没有设定 content type,那么数据的前 512 字节就会被用来检测 content type
- 默认WriteHeader 是200 OK
str:=`<html>
<head><title>Go web</title></head>
<body><h1>hello World</h1></body>
</html>`
w.Write([]byte(str))
WriteHeader 方法
- WriteHeader 方法接收一个整数类型(HTTP 状态码)作为参数,并把它作为 HTTP 响应的状态码返回
- 如果该方法没有显式调用,那么在第一次调用 Write 方法前,会隐式的调用 WriteHeader(http.StatusOK)
- 所以 WriteHeader 主要用来发送错误类的 HTTP 状态码
- 调用完 WriteHeader 方法之后,仍然可以写入到 ResponseWriter,但无法再修改 header 了
w.Header().Set("Location","http://google.com")
// 这个也是个重定向法子
w.WriteHeader(302)
Header 方法
Header方法返回 headers的map,可以进行修改。
修改后的headers将会体现在返回给客户端的HTTP响应里
// 结构体就类似于json的对象
// 这里是整了个结构体,转换成json格式了
type Post struct{
User string
Threads []string
}
func jsonExample(w http.ResponseWriter, r *http.Request){
w.Header().Set("Content-Type","application/json")
post:= &Post{
User: "timer",
Threads: []string{"first","second","third"},
}
json,_ := json.Marshal(post)
w.Write(json)
}
内置的 Response
NotFound 函数,
包装一个404码和一个额外信息
ServeFile 函数
从文件系统提供文件,返回给请求者
ServeContent
它可以把实现了io,ReadSeeker接口的人员内容返回给请求者。
还可以处理 Range 请求(范围请求),如果只请求了资源的一部分内容,
那么 ServeContent 就可以如此响应。
而 ServeFile 或 io.Copy 则不行。
Redirect
重定向
模板
模板的主要内容
简介 模板引擎 Action
参数、变量、管道 函数 模板组合
什么是模板?
- Web 模板就是预先设计好的 HTML 页面,它可以被模板引擎反复的使用,来产生 HTML 页面
- Go 的标准库提供了 text/template,html/template 两个模板库。text这个是任意格式文档,html这个是HTML格式专用
- 大多数 Go 的 Web 框架都使用这些库作为 默认的模板引擎
模板与模板引擎
模板和数据经过模板引擎 产生最终展示的HTML网页,写入到ResponseWriter中。
两种理想的模板引擎
无逻辑模板引擎
- 通过占位符,动态数据被替换到模板中
- 不做任何逻辑处理,只做字符串替换
- 处理完全由 handler 来完成
- 目标是展示层和逻辑的完全分离
逻辑嵌入模板引擎
- 编程语言被嵌入到模板中
- 在运行时由模板引擎来执行,也包含替换功能
- 功能强大
- 逻辑代码遍布 handler 和 模板,难以维护
Go 的模板引擎
- 主要使用的是 text/template,HTML 相关的部分使用了 html/template,是个混合体。
- 模板可以完全无逻辑,但又具有足够的嵌入特性
- 和大多数模板引擎一样,Go Web 的模板位于无逻辑和嵌入逻辑之间的某个地方
GO模板引擎的工作原理
在 Web 应用中,通常是由 handler 来触发模板引擎
handler 调用模板引擎,并将使用的模板传递给引擎
- 通常是一组模板文件和动态数据
模板引擎生成 HTML,并将其写入到 ResponseWriter
ResponseWriter 再将它加入到 HTTP 响应中,返回给客户端
关于模板
- 模板必须是可读的文本格式,扩展名任意。对于 Web 应用通常就是 HTML
里面会内嵌一些命令(叫做 action) - text/template 是通用模板引擎
- html/template 是 HTML 模板引擎
- action 位于双层花括号之间:{{ . }}
- 这里的 . 就是一个 action
- 它可以命令模板引擎将其替换成一个值
一个模板的例子
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Go Web Programming</title>
</head>
<body>
{{ . }}
</body>
</html>
使用模板引擎
- 解析模板源(可以是字符串或模板文件),从而创建一个解析好的模板结构
- 执行解析好的模板,并传入 ResponseWriter 和 数据。
- 这会触发模板引擎组合解析好的模板和数据,来产生最终的 HTML,并将它传递给 ResponseWriter
解析模板
ParseFiles
ParseGlob
Parse
解析其实就是进行语法分析
ParseFiles
- 解析模板文件,并创建一个解析好的模板 结构,后续可以被执行
- ParseFiles 函数是 Template struct 上 ParseFiles 方法的简便调用
- 调用 ParseFiles 后,会创建一个新的模板,模板的名字是文件名
- New 函数
- ParseFiles 的参数数量可变,但只返回一个模板
- 当解析多个文件时,第一个文件作为返回的模板(名、内容),其余的作为 map,供后续执行使用
//解析单个文件
t,_ := template.ParseFiles("wwwroot/tmpl.html")
t.Execute(w,"helloWorld")
//解析多个文件
ts,_ := template.ParseFiles("wwwroot/tmpl.html","wwwroot/index.html")
ts.ExecuteTemplate(w,"wwwroot/index.html","this is a index html")
// new函数 t1和t2等价
//t1
t,_:=template.ParseFiles("tmpl.html")
//t2
t:= template.New("tmpl.html")
t,_= t.ParseFiles("tmpl.html")
ParseGlob
对匹配给定模式的所有文件进行语法分析
t,_ := template.ParseGlob("*.html")
Parse
可以解析字符串模板,其它方式最终都会调用 Parse
t:=template.New("tmpl.html")
t,_= t.Parse(tmplhtmlStr)
t.Execute(w,参数)
LookUp方法
通过模板名来寻找模板,如果没找到就返回 nil
func loadTemplates() *template.Template{
result:= template.New("templates")
template.Must(result.ParseGlob("templates/*.html"))
return result
}
func lookUp(){
templates := loadTemplates()
http.HandleFunc("/",func(w http.ResponseWriter, r *http.Request) {
fileName :=r.URL.Path[1:]
// 找模板
t := templates.Lookup(fileName)
//如果找到的模板不为空
if t != nil {
err :=t.Execute(w,nil)
if err !=nil{
log.Fatalln(err.Error())
}
}
})
}
Must 函数
- 可以包裹一个函数,返回到一个模板的指针 和 一个错误。
- 如果错误不为 nil,那么就 panic
//用Must函数包裹函数,
// 来处理万一没找模板发生错误的情况
t:=template.Must(t.ParseFiles("tmpl.html"))
执行模板
Execute
参数是 ResponseWriter、数据
适用于单模板
模板集:只用第一个模板
ExecuteTemplate
参数是:ResponseWriter、模板名、数据
适用于模板集合
注意
都只能输入一个数据,这个数据是个接口,什么类型都可以。可以输入一个结构体,有字段,有方法。
模板 - Action
什么是 Action
- Action 就是 Go 模板中嵌入的命令,位于两组花括号之间 {{ xxx }}
- 就是一个 Action,而且是最重要的一个。它代表了传入模板的数据
- Action 主要可以分为五类:
- 条件类
- 迭代/遍历类
- 设置类
- 包含类
- 定义类
条件类
{{ if arg }}
some content
{{ end }}
{{ if arg }}
some content
{{ else }}
other content
{{ end }}
迭代/遍历类
- 用来遍历数组,slice map 或者 channel等
{{ range array}}
dot is set to the element {{ . }}
{{ else }}
no thing to show
{{ end }}
{{range $key ,$value := . }}
the key is {{$key}} and the value is {{$value}}
{{end}}
迭代循环中的{{ . }}代表的是当前被迭代的元素
回落机制,当传入的东西为空时,启用else
设置类
它允许在指定范围内,让“.”来表示其它指定的值(arg)
也有回落机制
{{ with MySetArg }}
dot is set to {{ . }}
{{ end }}
{{ with MySetArg }}
dot is set to {{ . }}
{{ else }}
//当 MySetArg 自己设置值是空值时,还是用原来的参数
the dot is still {{ . }}
{{ end }}
包含类
嵌套模板执行时建议使用ExecuteTemplate
{{ template "name" }}
它允许你在模板中包含其它的模板
{{ template "name" arg }}
给被包含模板传递参数
向被包含的模板传参,传的 是 . 的话,
就是把包含模板的参数传进去了
定义类
define action
Layout
layout模板就是网页中固定的部分,它可以被多个网页重复使用
Include(包含)action 的形式:{{ template "name" . }}以这种方式做 layout 模板是不可行的。
正确的做法是在模板文件里面使用 define action 再定义一个模板。
同一模板文件里可以定义多个不同的模板
不同模板文件里可以定义同名模板
<!-- 定义模板 -->
{{ define "layout"}}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- Font Awesome -->
<link
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css"
rel="stylesheet"
/>
<!-- Google Fonts -->
<link
href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap"
rel="stylesheet"
/>
<!-- MDB -->
<link
href="https://cdnjs.cloudflare.com/ajax/libs/mdb-ui-kit/6.2.0/mdb.min.css"
rel="stylesheet"
/>
</head>
<body>
<nav class="navbar">
<a href="#" class="navbar-brand">这是个可复用组件 </a>
</nav>
<!-- 包含模板 -->
{{template "content" . }}
</body>
<!-- MDB -->
<script
type="text/javascript"
src="https://cdnjs.cloudflare.com/ajax/libs/mdb-ui-kit/6.2.0/mdb.min.js"
></script>
</html>
{{ end }}
block 块动作
如果一个模板中包含{{template "content"}}这个模板,如果你解析的时候没有传入content模板,程序就会崩溃。所以添加默认模板
{{ block "content" . }}
some thing
{{ end }}
假如没有传入content模板,就会启用block定义的默认模板,程序可以继续执行
参数、函数和管道
参数
- 参数就是模板里面用到的值。
- 可以是 bool、整数、string …
- 也可以是 struct、struct 的字段、数组的 key 等等
- 参数可以是变量、方法(返回单个值或返回一个值和一个错误)或函数
- 参数可以是一个点“.”,也就是传入模板引擎的那个值。
记得大写首字母!!!
在 Action 中设置变量
可以在 action 中设置变量,变量以 $ 开头:
$variable := value
一个迭代 action 的例子:
{{ range $key, $value := . }}
The key is {{ $key }} and the value is {{ $value }}
{{ end }}
逻辑运算符
eq 等于 / ne 不等于
lt 小于/ gt 大于
le 小于等于 / ge 大于等于
and 和
or 或
not 非
if eq . "hello"
如果传入参数和hello相等
管道
- 管道是按顺序连接到一起的参数、函数和方法。
- 和 Unix 的管道类似
- 例如:{{ p1 | p2 | p3 }}
- p1、p2、p3 要么是参数,要么是函数
- 管道允许我们把参数的输出发给下一个参数,下一个参数由管道(|)分隔开。
{{ 12.345 | printf "%.2f" }}
{{ . | turnDouble | printf "%.2f"}}
函数
自定义函数
- 参数可以是一个函数
- Go 模板引擎提供了一些基本的内置函数,功能比较有限。例如 fmt.Sprint 的各类变体等
- 开发者可以自定义函数:
- 可以接收任意数量的输入参数
- 返回:
一个值
一个值+一个错误
- 返回:
内置函数
- define、template、block
- html、js、urlquery。对字符串进行转义,防止安全问题
- 如果是 Web 模板,那么不会需要经常使用这些函数。
- index
- print/printf/println
- len
- with
如何自定义函数
template.Funcs(funcMap FuncMap) *Template
type FuncMap map[string]interface{}
value 是函数
可以有任意数量的参数
返回单个值的函数或返回一个值+一个错误的函数
- 创建一个 FuncMap(map 类型)。
- key 是函数名
- value 就是函数
- 把 FuncMap 附加到模板
func divfunc(w http.ResponseWriter,r * http.Request){
funcMap := template.FuncMap{"fdate":formDate}
t:=template.New("test.html").Funcs(funcMap)
t.ParseFiles("test.html")
t.Execute(w,time.Now())
}
func formDate(timer time.Time) string{
layout :="2006-01-02"
return timer.Format(layout)
}
html那边
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
{{ . | fdate}}
或者
{{ fdate . }}
</body>
</html>
常见用法:template.New(“”).Funcs(funcMap).Parse(…)
- 调用顺序非常重要
可以在管道中使用
也可以作为正常函数使用
管道更强大且灵活
GO web学习(二)的更多相关文章
- java web 学习二(Tomcat服务器学习和使用1)
一.Tomcat服务器端口的配置 Tomcat的所有配置都放在conf文件夹之中,里面的server.xml文件是配置的核心文件. 如果想修改Tomcat服务器的启动端口,则可以在server.xml ...
- ReactJS入门学习二
ReactJS入门学习二 阅读目录 React的背景和基本原理 理解React.render() 什么是JSX? 为什么要使用JSX? JSX的语法 如何在JSX中如何使用事件 如何在JSX中如何使用 ...
- java web 学习笔记 编码问题总结
java web 学习笔记 编码问题总结 1.非form表单中提交的中文参数---------------------------传递给Servlet服务器时,默认以iso-8859-1解码 ...
- SpringCloud学习(二):微服务入门实战项目搭建
一.开始使用Spring Cloud实战微服务 1.SpringCloud是什么? 云计算的解决方案?不是 SpringCloud是一个在SpringBoot的基础上构建的一个快速构建分布式系统的工具 ...
- SpringMVC入门学习(二)
SpringMVC入门学习(二) ssm框架 springMVC 在上一篇博客中,我简单介绍了一下SpringMVC的环境配置,和简单的使用,今天我们将进一步的学习下Springmvc的操作. mo ...
- Java web学习总结
javaweb学习总结(十四)——JSP原理 孤傲苍狼 2014-07-24 09:38 阅读:46603 评论:37 JavaWeb学习总结(十三)——使用Session防止表单重复提交 孤 ...
- Spring Boot 项目学习 (二) MySql + MyBatis 注解 + 分页控件 配置
0 引言 本文主要在Spring Boot 基础项目的基础上,添加 Mysql .MyBatis(注解方式)与 分页控件 的配置,用于协助完成数据库操作. 1 创建数据表 这个过程就暂时省略了. 2 ...
- Java反射:Web学习的灵魂
反射:Web学习的灵魂 我们从最初的 javac -HelloWorld.java,到面向对象部分,我们可以将Java代码在计算机中经历的阶段分为三部分:Scource源代码阶段 -- Class类对 ...
- Java Web学习笔记之---EL和JSTL
Java Web学习笔记之---EL和JSTL (一)EL (1)EL作用 Expression Language(表达式语言),目的是代替JSP页面中复杂的代码 (2)EL表达式 ${变量名} ( ...
- Java Web学习笔记之---JSP
Java Web学习笔记之---JSP (一)JSP常用语法 (1)HTML注释 <!--所要注释的内容 --> 在客户端显示一个注释. (2)隐藏注释 <%--所要注释的内容--% ...
随机推荐
- 四月六号java基础学习
四月六号 1.今天学习了JAVA语言特点,有以下几个特点: 1)简单易学:相对于C/c++语言,java语言省去了指针(pointer).联合体(Unions)以及结构体(struct) 2)面向对象 ...
- DG:windows密码文件
问题描述:搭建DG,找不到密码文件的位置,就给备库重新生成了一个密码文件,传到了备库,但是拉到了备库以后,恢复过程中,trace日志在报错,后来才知道windows下的密码文件跟linux平台下的面文 ...
- MySQL(十四)分析查询语句Explain 七千字总结
分析查询语句:EXPLAIN 1概述 定位了查询慢的SQL之后,就可以使用EXPLAIN或者DESCRIBE工具做针对性的分析查询.两者使用方法相同,并且分析结果也是相同的. MySQL中有专 ...
- C++ sizeof与strlen,并借此明晰内存对齐
前言 sizeof()与strlen()都是为了获取对象的长度.在正常编写C++的算法程序代码时,可能这两个都很少用到,因为各种stl容器的封装已经给了我们很大的便利,比如我们在想要获取自定义的vec ...
- 创建SpringBoot项目,在yml中配置数据库, driver-class-name: com.mysql.cj.jdbc.Driver标红报错解决方式
一.报错原因 com.mysql.cj.jdbc.Driver一直标红报错,原因在于pom.xml中mysql包没有下载下来,或者在创建项目的时候有问题 二.解决方案 在pom.xml添加 <d ...
- PWN 学习日志(1): pwntools简单使用与栈溢出实践
常用的模块 模块 功能 asm 汇编与反汇编 dynelf 远程符号泄漏 elf 对elf文件进行操作 memleak 用于内存泄漏 shellcraft shellcode生成器 gdb 配合gdb ...
- ROS机器人雷达跟随
ROS机器人雷达跟随 初始化 打开一个终端输入: ssh clbrobot@ip # 连接小车 roslaunch clbrobot bringup.launch # 激活主板 开启摄像头 开新终端输 ...
- python-SSTI模板注入
一.python_SSTI模板注入介绍 ssti漏洞成因 ssti服务端模板注入,ssti主要为python的一些框架 jinja2 mako tornado django,PHP框架smarty t ...
- P8936 月下缭乱 Sol
考虑对操作的区间 \([l_i,r_i]\) 的下标进行扫描线而不是对操作的值扫.用 \(m\) 个 set 动态维护 \(x_i\) 对应的操作的下标集合,再用一个可删堆来维护当前所有操作 \(x_ ...
- 2023-05-07:给你一个大小为 n x n 二进制矩阵 grid 。最多 只能将一格 0 变成 1 。 返回执行此操作后,grid 中最大的岛屿面积是多少? 岛屿 由一组上、下、左、右四个方向相
2023-05-07:给你一个大小为 n x n 二进制矩阵 grid .最多 只能将一格 0 变成 1 . 返回执行此操作后,grid 中最大的岛屿面积是多少? 岛屿 由一组上.下.左.右四个方向相 ...