《Go Web 编程》之第1章 Go与Web应用

尉迟冯浩
2023-12-01

第1章 Go与Web应用

1.1 Go语言构建Web应用

Go适合编写需要快速运行的服务器端程序。
过程式编程,函数式编程,内置并发,包管理系统,垃圾收集,丰富标准库,优秀开源库。
大规模可扩展的Web应用具备特质:

  • 可扩展;
  • 模块化
  • 可维护;
  • 高性能。

1.1.1 Go与可扩展Web应用

可扩展的(scalable),可简单快速地提升应用性能,线性的,可通过添加更多硬件来获取更强的请求处理能力。

  • 垂直扩展(vertical scaling),即提升单台设备的CPU数量或者性能;
  • 水平扩展(horizontal scaling),即通过增加计算机的数量来提升性能。

1.1.2 Go与模块化Web应用

模块化组件可替换,更容易添加、移除或修改,满足不断变化的需求。
复用模块化组件可降低软件开发费用。
静态类型语言Go,可通过借口机制描述行为,实现动态类型匹配(dynamic typing)。
Go常用于创建微服务(microservice)。

1.1.3 Go与可维护Web应用

简洁可读语法,灵活清晰包管理,一整套优秀工具(gofmt、godoc等),内置测试支持。

1.1.4 Go与高性能Web应用

高性能,短时间内处理大量请求,快速响应。

1.2 Web应用工作原理

客户端向服务器发出请求,服务器接收请求,执行指定的操作,然后返回文件,对客服端做出响应。
应用(application)是一个与用户进行互动并帮助用户执行指定活动的软件程序。
Web应用看作特殊的Web服务,狭义定义:

  • 向发送命令的客户端返回HTML,且客户端向用户展示渲染后的HTML;
  • 使用HTTP协议进行数据传送。

1.3 HTTP简介

应用层通信协议,使用文本进行数据传输。
HTTP/0.9,只有GET方法。
HTTP/1.1
HTTP/2.0
HTTP是一种无状态、由文本构成的请求-响应(request-response)协议,使用客户端-服务器(client-server)计算模型。
HTTP以纯文本非二进制方式发送和接收协议数据。

1.4 Web应用诞生

CGI(Common Gateway Interface,通用网关接口),与服务器对接的程序。
SSI(server-side includes,服务器包含),HTML文件中嵌入指令。

1.5 HTTP请求

(1)请求行(request-line);
(2)零或多个请求首部(header);
(3)一个空行;
(4)可选报文主体(body)。
GET /Prtocols/rfc2616/rfc2616.html HTTP/1.1
Host: www.w3.org
User-Agent: Mozilla/5.0
(empty line)

1.5.1 请求方法

客户端对资源执行的操作。

  • GET
    返回指定资源。

  • HEAD
    不获取报文主体,取得响应首部。

  • POST
    传递报文主体中的数据。

  • PUT
    使用报文主体中的数据进行设置。不存在则创建,存在则替换。

  • DELETE
    删除资源。

  • TRACE
    返回请求本身。

  • OPTIONS
    返回支持的HTTP方法列表。

  • CONNECT
    建立网络连接,用于设置SSL隧道以开启HTTPS功能。

  • PATCH
    使用报文主体中的数据进行修改。

1.5.2 安全的请求方法

safe,只要求服务器提供信息而不会对服务器的状态做任何修改。

  • 安全的请求方法
    GET、HEAD、OPTIONS、TRACE

  • 不安全的请求方法
    POST、PUT、DELETE

1.5.3 幂等的请求方法

idempotent,使用相同的数据进行第二次调用的时候,不会对服务器的状态造成任何改变。

  • 幂等的请求方法
    GET、HEAD、OPTIONS、TRACE、PUT、DELETE

  • 不幂等的请求方法
    POST

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

支持GET和POST方法。
POST方法通过HTML表单实现:HTML的form标签存在method属性。

1.5.5 请求首部

宿主(Host)是HTTP1.1唯一强制要求的首部。

首部字段作用描述
Accept能够接收的内容类型。text/html等
Accept-Charset字符集编码。utf-8等
Authorization发送基本的身份验证证书
Cookie回传所有cookie
Content-Length请求主体的字节长度
Content-Type主体内容类型
Host服务器名称及端口号
Referer发起请求的页面地址
User-Agent发起请求的客户端描述

1.6 HTTP响应

(1)一个状态行;
(2)零或多个响应首部;
(3)一个空行;
(4)可选报文主体。
200 OK
Date: Sat, 22 Nov 2014 12:58:58 GMT
Server: Apache/2
Content-Length: 33115
Content-Type: text/html; charset=iso-8859-1
(empty line)
<!DOCTYPE html>...</html>

1.6.1 响应状态码

状态码类型作用描述
1XX情报状态码。收到请求并进行了处理。
2XX成功状态码。收到请求并成功地进行了处理。
3XX重定向状态码。收到请求并成功地进行了处理,客户端还需要进行处理。多用于URL重定向。
4XX客户端错误状态码。请求出现问题。常见"404 Not Found"
5XX服务器错误状态码。服务器无法正确处理。常见"500 Internal Server Error"

1.6.2 响应首部

首部字段作用描述
Allow服务器支持的请求方法
Content-Length响应主体的字节长度
Content-Type主体内容类型
DateGMT格式时间
Location仅在重定向时使用,指定URL
Server服务器域名
Set-Cookie设置客户端cookie,可包含多个
WWW-Authenticate告知客户端Authorization请求首部应提供何种类型的身份验证信息。常与"401 Unauthorized"状态行一同发送

1.7 URI

统一资源名称(Uniform Resource Name,URN),使用字符串表示资源名字;
统一资源定位符(Uniform Resource Location,URL),使用字符串表示资源所在位置。
统一资源标识符(Uniform Resource Identifer,URI),包含URN和RUL。

URI一般格式:

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

方案名称(scheme name)记录使用方案,定义了URI其余部分结构。
分层部分(hierarchical part)包含资源的识别信息,以分层方式进行组织。若以双斜线(//)开头,可含用户信息(@结尾)。分层路径由分段(segment)组成,使用单斜线(/)分隔。
查询参数(query),&分隔的键值对组成。
片段(fragment),标识次级资源(secondary resource)。片段由客户端进行处理,web浏览器发送URI时会去掉其中片段。

http://sausheong:password@www.example.com/docs/file?name=sausheong&location=singapore#summary

URL编码(百分号编码)对特殊符号(?#等)进行转换。
空格ASCII编码为32,十六进制为20,URL编码为%20。

中文URL编码,先转换为UTF-8编码,然后对每个字节以%XX表示。

摘要URL编码为%E6%91%98%E8%A6%81。

1.8 HTTP/2简介

二进制协议,语法分析高效,紧凑和健壮。
完全多路复用(fully multiplexed),多个请求和响应在同一时间内使用同一个连接,首部压缩,允许服务器推送(push)响应至客户端。

1.9 Web应用组成部分

web应用就是执行如下任务的程序:
(1)通过HTTP协议,以HTTP请求报文的形式获取客户端输入;
(2)处理HTTP请求,执行必要操作;
(3)生成HTML,以响应报文的形式通过HTTP返回给客户端。

1.9.1 处理器

接收和处理客户端发来的请求;
调用模板引擎;
填充模板引擎生成的HTML数据至回传给客户端的响应报文中。

MVC(Model-View-Controller)模式。
模型表示底层数据;
视图以可视化方式向用户展示模型;
控制器会根据用户输入对模型进行修改。
模型变化时,视图自动更新。

web应用框架中,模型通过结构或对象映射到数据库,视图被渲染为HTML,控制器负责路由请求和模型访问的管理。

1.9.2 模板引擎

模板引擎(template engine)通过模板和数据生成最终的HTML。

  • 静态模板(无逻辑模板)
    替换占位符,无或少量逻辑代码。

  • 动态模板
    占位符+编程语言结构(条件、迭代、变量等)。

1.10 Hello Go Web

hello_go_web.go

package main

import (
	"fmt"
	"net/http"
)

func handler(writer http.ResponseWriter, request *http.Request) {
	fmt.Fprintf(writer, "Hello World, %s!", request.URL.Path[1:])
}

func main() {
	http.HandleFunc("/", handler)
	http.ListenAndServe(":8080", nil)
}
go run hello_go_web.go
http://localhost:8080/test/here
 类似资料: