从零开始学Go web——第一天

​ “工欲善其事必先利其器”!学习web的第一天,当然是要学习与web息息相关的就是HTTP协议等知识点,因此第一天让我们一起聊聊Go与web的关系、web应用、HTTP的简介/请求/响应以及HTTP2协议, 开启快乐学习Go web!

一、Go与web应用简介

​ Go语言是一门函数式和过程式并存语言,并且提供了现代化包管理系统、垃圾收集机制、以及各种功能强大的标准库。

​而web应用具备的四个条件:

  • 可扩展的:简单、快速地提升应用的性能以便处理更多的请求。比如管理者可以通过添加硬件来提升请求处理能力
  • 模块化:大规模的web应用应该由可替换的组件构成,使得可以快速添加、移除、修改,以便更好地复用。
  • 可维护
  • 高性能

1.1 Go的可扩展性

Go语言的扩展包括两个方面:

  • 水平扩展: Go语言可以编译为不包含动态依赖关系的静态二进制文件,从而可以在没有安装Go语言的系统里面部署Go web应用。
  • 垂直扩展: Go web应用只需要一个操作系统线程,就可以高效运行数十万个goroutine。

1.2 Go的模块化

Go语言的模块化包括以下两个方面:

  • Go语言的接口。接口可以实现动态类型匹配机制,其中Go语言的函数可以接受接口作为参数,用户只需要实现了接口的方法,就可以将接口作为参数传递给函数,实现动态类型传参。同时,Go语言也实现了一个空接口,可以把任何类型的值作为函数的实际参数。
  • 创建微服务。创建多个规模较小的Go服务(也就是一个个Go包)并且将它们组合为当个web应用。

1.3 Go的可维护

  • gofmt格式化源代码
  • godoc对go源代码以及注释进行语法分析,并且使用html、纯文本或者其他多种格式生成文档。
  • gotest自动寻找与源代码位于同一个包的测试代码,并进行功能测试和性能测试。同时也提供了web测试工具,如httptest。

1.4 Go的高性能

  • Go程序会编译为本地码,比一般的解释型语言要更加快
  • Go的goroutine对并发编程有了更好的支持。

二、web应用

2.1 工作原理

web服务器:对客户端发送的HTTP请求做出响应,并且将响应HTTP返回给客户端。一个web服务器就是一个web应用。

web应用:对请求进行处理,然后执行应用程序中预先设定好的操作。

因此,web服务器是一种特殊的web应用,只会返回请求的文件。若我们要想构建一个web应用,必须符合以下两个条件:

  • 必须向发送命名请求的客户端返回HTML,而客户端会展示渲染后的HTML
  • 在向客户端传输数据的时候必须使用HTTP协议

2.2 各个组成部分

web应用主要包括如下三部分:

  • HTTP请求报文获取客户端输入
  • 处理请求报文
  • 生成HTML,并且以HTTP响应报文的形式返回给客户端。

为了完成这些步骤,web应用被分为处理器(handler)和模板引擎(template engine)两个部分。

2.2.1 处理器

​ 接收和处理客户端请求,调用模板引擎生成HTML并且将数据填充至响应报文中。

2.2.2 模板引擎

​ 通过模板和数据生成最终的HTML,分为静态模板和动态模板:

  • 静态模板:夹杂着占位符的HTML。将占位符替换为对应数据来生成最终的HTML,不包含或者只包含少量的逻辑代码,也称为无逻辑模板
  • 动态模板:包含HTML、占位符、编程语言结构,如条件语句、变量等。如JSP、ASP等及时动态模板引擎

    三、HTTP简介

    ​ HTTP是万维网的应用层通信协议。目前总共有两个版本:HTTP1.1和HTTP2.0(又称为HTTP/2),目前使用最广泛的还是HTTP1.1。

​ 那么什么是HTTP呢?HTTP是一种无状态、文本构成的请求-响应协议,使用的是客户端-服务器的计算模型。

  • 无状态:只知道当前的请求和响应,后续的请求对之前的请求一无所知。
  • 请求和响应:发送端发送请求给接收端,接收端响应数据给发送端。
  • 客户端-服务端:客户端称为客户代理,服务端为客户端提供服务。

四、HTTP请求

4.1 请求的文本数据

​ HTTP请求的数据也称为HTTP请求报文,主要有以下四部分组成:

  • 请求行(request-line)
  • 请求首部(header,零个或者多个)
  • 空行(一个)
  • 报文主体(body,可选)

典型的HTTP请求报文如下所示:

GET / HTTP/1.1               # GET代表的是请求方法(request method),之后跟的是URI,以及所用的HTTP版本
Host: 127.0.0.1:8083         # 请求首部
User-Agent: curl/7.58.0     # 请求首部
Accept: */*                 # 请求首部
(空行)                           # 空行,必须存在

注: #后添加的是注释

4.2 请求方法

4.2.1 请求方法类型

​ 请求方法表明了客户端想要对资源执行的操作。HTTP1.1具有GET、PUT、DELETE、OPTIONS、TRACE、CONNECT这六个方法。HTTP1.1只需要实现GET方法和HEAD方法,其它方法都是可选的

  • GET:命令服务器返回指定的资源
  • HEAD:不要求服务器返回报文的主体。通常应用于只需要获取响应首部。
  • POST: 报文主体数据传递给URI指定资源,数据做啥由服务器本身决定。
  • PUT: 报文主体数据设置为URI指定资源,若URI指定位置有数据则进行替换,否则在URI指定位置上新建一个资源
  • DELETE:删除服务器指定URI资源
  • TRACE: 返回请求本身。
  • OPTIONS: 返回它支持的HTTP方法列表
  • CONNECT: 客户端和服务器建立网络连接。通过用于设置SSL隧道以开启HTTPS功能
  • PATCH: 使用报文主体中的数据对指定URI资源进行修改

4.2.2 安全的请求方法

​ 不会对服务器状态进行修改。GET、HEAD、OPTIONS、TRACE是安全的请求方法

4.2.2 幂等的请求方法

​ 第二次调用,不会对服务器状态进行改变。安全的请求方法是幂等的,此外PUT和DELETE也是幂等的。

4.2.2 浏览器对请求方法的支持

​ GET是所有浏览器支持的。

​ 对于传输的数据来说,HTML不支持除了GET和POST之外其他HTTP请求方法。但是用户可以通过XHR来获取PUT和DELETE的支持,该技术可以实现XML、JSON、纯文本等任何格式的请求和响应。

4.3 请求首部

​ 记录了与请求本身以及客户端相关的信息。由任意多个冒号分隔的纯文本键值对组成,以回车和换行结尾

​ 注:Host首部字段是HTTP1.1强制要求的首部,其余的都是可选的。

​ 若请求报文中包含了请求主题,那么请求首部需要携带内容长度(Content-Length)或者传输编码(Transfer-Encoding)字段。


五、HTTP响应

​ HTTP响应报文是对HTTP请求报文的回复,主要有以下四部分组成:

  • 状态行(一个)
  • 响应首部(header,零个或者多个)
  • 空行(一个)
  • 报文主体(body,可选)

典型的HTTP响应报文如下所示:

HTTP/1.1 200 OK                                 # 状态行,包含HTTP协议类型,状态码(status code)和相应的原因短语(reason phrase)
Content-Type: text/plain; charset=utf-8         # 响应首部
Date: Mon, 27 Nov 2023 08:21:42 GMT             # 响应首部
Content-Length: 12                                 # 响应首部
(空行)
Hello World!                                     # 报文主体

5.1 响应状态码

​ HTTP响应类型总共有5种,分别以不同的数字作为前缀:

5.2 响应首部

​ 格式和请求首部一样。为客户端提供更多与请求相关或者与客户端诉求相关的信息。常用的响应首部如下所示:

5.3 URI

​ 统一资源标识符(Uniform Resource Identifier,URI),使用位置字符串表示互联网资源。字符串表示资源名称:URN,字符串表示资源路径:URI。URL是一个涵盖的术语,包含了URI和URN。

​ URI的一般格式:

<方案名称>:<分层部分>[?<查询参数>][#片段]

注:只有方案名称和分层部分是必须的,其它是可选的。

  • 方案名称(scheme name):记录了URI使用的方案,定义了URI其余部分结构。URI具有大量的方案,在HTTP中使用的是HTTP方案。
  • 分层部分(hierarchical part):包含了资源的识别信息。若以//开头,则包含了可选的用户信息(以@结尾)。在用户信息(可选的)后面跟着的是分层路径,该路径由分段组成,各个分段之间由/分隔
  • 查询参数:由一连串的键值对构成,它们之间由&分隔
  • 片段:由#为前缀,对URI定义的次级资源进行标识。

由于URI的片段是由客户端处理的,而web浏览器在将URI发送给服务器之前,会将片段移除,若想要获取片段的信息,则需要使用JS或者某个HTTP客户端库,将URI片段包含在GET请求里面

​ HTTP URI方案示例:

http://pzs:password@www.example.com/docs/file?name=pzs&location=china#summy      # http代表方案。@之前分段记录了用户名和密码,而之后的www.example.com/docs/file记录的是分层部分的其余部分,其中最高层为www.example.com,后面的两个层为doc何file,每个分层由/分隔。?之后是查询参数,最后有一个#结尾的片段。

​ Tips: 每个URL是一个独立字符串,不能使用空格。同时#和?有特殊意义,不能用于其它用途。若想要避开这些限制,则必须使用URL编码来将特殊符号进行转换。示例如下所示:

http://pzs@www.example.com/docs/file?name=p zs&location=china#summy 
经过转换后为:
http://pzs@www.example.com/docs/file?name=p%20zs&location=china#summy #空格的ASCII码为20,然后在前面再加上一个%形成URL编码

六、HTTP/2

一种二进制通信协议,使得语法分析更加高效、紧凑、健壮。当然这样的话就无法使用telnet程序进行调试了。

HTTP2是多路复用的,多个请求和响应可以同时使用一个连接。而HTTP1.1只能一个请求和响应对应一个连接。

HTTP2允许对首部进行压缩,减少数据传输量,并且允许服务器将响应推送给客户端。

在新版本的Go语言中使用HTTPS则默认使用HTTP2协议

好啦,第一天的web学习到此就结束喽!第二天让我们一起来写属于自己的第一个Go web程序!