跟着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学习(二)的更多相关文章

  1. java web 学习二(Tomcat服务器学习和使用1)

    一.Tomcat服务器端口的配置 Tomcat的所有配置都放在conf文件夹之中,里面的server.xml文件是配置的核心文件. 如果想修改Tomcat服务器的启动端口,则可以在server.xml ...

  2. ReactJS入门学习二

    ReactJS入门学习二 阅读目录 React的背景和基本原理 理解React.render() 什么是JSX? 为什么要使用JSX? JSX的语法 如何在JSX中如何使用事件 如何在JSX中如何使用 ...

  3. java web 学习笔记 编码问题总结

       java web 学习笔记 编码问题总结 1.非form表单中提交的中文参数---------------------------传递给Servlet服务器时,默认以iso-8859-1解码 ...

  4. SpringCloud学习(二):微服务入门实战项目搭建

    一.开始使用Spring Cloud实战微服务 1.SpringCloud是什么? 云计算的解决方案?不是 SpringCloud是一个在SpringBoot的基础上构建的一个快速构建分布式系统的工具 ...

  5. SpringMVC入门学习(二)

    SpringMVC入门学习(二) ssm框架 springMVC  在上一篇博客中,我简单介绍了一下SpringMVC的环境配置,和简单的使用,今天我们将进一步的学习下Springmvc的操作. mo ...

  6. Java web学习总结

    javaweb学习总结(十四)——JSP原理 孤傲苍狼 2014-07-24 09:38 阅读:46603 评论:37     JavaWeb学习总结(十三)——使用Session防止表单重复提交 孤 ...

  7. Spring Boot 项目学习 (二) MySql + MyBatis 注解 + 分页控件 配置

    0 引言 本文主要在Spring Boot 基础项目的基础上,添加 Mysql .MyBatis(注解方式)与 分页控件 的配置,用于协助完成数据库操作. 1 创建数据表 这个过程就暂时省略了. 2 ...

  8. Java反射:Web学习的灵魂

    反射:Web学习的灵魂 我们从最初的 javac -HelloWorld.java,到面向对象部分,我们可以将Java代码在计算机中经历的阶段分为三部分:Scource源代码阶段 -- Class类对 ...

  9. Java Web学习笔记之---EL和JSTL

    Java Web学习笔记之---EL和JSTL (一)EL (1)EL作用 Expression  Language(表达式语言),目的是代替JSP页面中复杂的代码 (2)EL表达式 ${变量名} ( ...

  10. Java Web学习笔记之---JSP

    Java Web学习笔记之---JSP (一)JSP常用语法 (1)HTML注释 <!--所要注释的内容 --> 在客户端显示一个注释. (2)隐藏注释 <%--所要注释的内容--% ...

随机推荐

  1. 四月六号java基础学习

    四月六号 1.今天学习了JAVA语言特点,有以下几个特点: 1)简单易学:相对于C/c++语言,java语言省去了指针(pointer).联合体(Unions)以及结构体(struct) 2)面向对象 ...

  2. DG:windows密码文件

    问题描述:搭建DG,找不到密码文件的位置,就给备库重新生成了一个密码文件,传到了备库,但是拉到了备库以后,恢复过程中,trace日志在报错,后来才知道windows下的密码文件跟linux平台下的面文 ...

  3. MySQL(十四)分析查询语句Explain 七千字总结

    分析查询语句:EXPLAIN 1概述 ​ 定位了查询慢的SQL之后,就可以使用EXPLAIN或者DESCRIBE工具做针对性的分析查询.两者使用方法相同,并且分析结果也是相同的. ​ MySQL中有专 ...

  4. C++ sizeof与strlen,并借此明晰内存对齐

    前言 sizeof()与strlen()都是为了获取对象的长度.在正常编写C++的算法程序代码时,可能这两个都很少用到,因为各种stl容器的封装已经给了我们很大的便利,比如我们在想要获取自定义的vec ...

  5. 创建SpringBoot项目,在yml中配置数据库, driver-class-name: com.mysql.cj.jdbc.Driver标红报错解决方式

    一.报错原因 com.mysql.cj.jdbc.Driver一直标红报错,原因在于pom.xml中mysql包没有下载下来,或者在创建项目的时候有问题 二.解决方案 在pom.xml添加 <d ...

  6. PWN 学习日志(1): pwntools简单使用与栈溢出实践

    常用的模块 模块 功能 asm 汇编与反汇编 dynelf 远程符号泄漏 elf 对elf文件进行操作 memleak 用于内存泄漏 shellcraft shellcode生成器 gdb 配合gdb ...

  7. ROS机器人雷达跟随

    ROS机器人雷达跟随 初始化 打开一个终端输入: ssh clbrobot@ip # 连接小车 roslaunch clbrobot bringup.launch # 激活主板 开启摄像头 开新终端输 ...

  8. python-SSTI模板注入

    一.python_SSTI模板注入介绍 ssti漏洞成因 ssti服务端模板注入,ssti主要为python的一些框架 jinja2 mako tornado django,PHP框架smarty t ...

  9. P8936 月下缭乱 Sol

    考虑对操作的区间 \([l_i,r_i]\) 的下标进行扫描线而不是对操作的值扫.用 \(m\) 个 set 动态维护 \(x_i\) 对应的操作的下标集合,再用一个可删堆来维护当前所有操作 \(x_ ...

  10. 2023-05-07:给你一个大小为 n x n 二进制矩阵 grid 。最多 只能将一格 0 变成 1 。 返回执行此操作后,grid 中最大的岛屿面积是多少? 岛屿 由一组上、下、左、右四个方向相

    2023-05-07:给你一个大小为 n x n 二进制矩阵 grid .最多 只能将一格 0 变成 1 . 返回执行此操作后,grid 中最大的岛屿面积是多少? 岛屿 由一组上.下.左.右四个方向相 ...