8.1.1 创建简单的HTTP服务器
在 Go 语言中,创建一个简单的 HTTP 服务器非常直观且高效。Go 的标准库 net/http
提供了构建 HTTP 服务所需的工具和方法。下面,我们将介绍一些基本的 HTTP 原理,以及如何使用 Go 创建一个基础的 HTTP 服务器。
HTTP 基本原理
HTTP(Hypertext Transfer Protocol)是一种无状态、应用层的协议,主要用于 Web 浏览器和 Web 服务器之间的通信。其核心概念包括:
- 请求(Request): 客户端向服务器发送请求报文。
- 响应(Response): 服务器对请求进行处理并返回响应报文给客户端。
- 方法(Method): 表示请求的动作,例如 GET、POST、PUT、DELETE 等。
- 状态码(Status Code): 响应中包含的代码,指示请求的结果(如 200 表示成功,404 表示未找到)。
- 头部(Headers): 包含请求或响应的元数据。
- 主体(Body): 实际的数据负载。
HTTP 服务器通信原理与流程
下面是一个 Go HTTP 服务器工作的典型流程:
- 启动服务器:
http.ListenAndServe
函数被调用,程序开始在指定端口上监听传入的连接请求。
- 等待客户端请求:
- 服务器处于监听状态,等待客户端(如浏览器或 API 客户端)发起 HTTP 请求。
- 接收请求:
- 当客户端发送请求时,服务器接受此连接。
- 解析 HTTP 请求报文,提取方法(GET, POST 等)、路径、头部信息和请求体等内容。
- 路由请求:
- 通过
http.ServeMux
或第三方库(如gorilla/mux
),将请求路由到相应的处理器函数。 - 路由根据 URL 路径匹配合适的处理器。
- 通过
- 处理请求:
- 调用处理器函数,处理业务逻辑,如查询数据库、计算结果或生成响应数据。
- 处理完成后,通过
http.ResponseWriter
构造 HTTP 响应,包括设置状态码、头部信息和响应体。
- 发送响应:
- 将 HTTP 响应发送回客户端。
- 响应被解析并呈现给用户或者被应用程序消费。
- 关闭连接(如果是短连接):
- 对于 HTTP/1.0 和未启用 Keep-Alive 的 HTTP/1.1 连接,在响应后关闭 TCP 连接。
- 对于支持持久连接的情况下(Keep-Alive),服务器可能保持连接以便重用。
流程图结构
[启动服务器] --> [等待客户端请求]
[等待客户端请求] --> [接收请求] --> [路由请求] --> [处理请求] --> [发送响应]
[发送响应] --> [是否保持连接?]
[是否保持连接?] --否--> [关闭连接]
[是否保持连接?] --是--> [等待客户端请求]
Go 的 net/http 包核心数据结构
在 Go 语言中,HTTP 功能是由标准库 net/http
提供的。net/http
包封装了 HTTP 协议的复杂性,使开发者能够轻松地创建客户端和服务器应用程序。这里,我们将探讨一些核心的数据结构和类型,它们在 Go 的 net/http
包中用于实现 HTTP 的功能。
核心数据结构
-
http.Request
http.Request
表示一个 HTTP 请求,并包含请求的所有信息,例如方法、URL、头部、主体等。
type Request struct { Method string // 请求的方法(GET, POST 等) URL *url.URL // 请求的 URL Proto string // HTTP 协议版本 Header Header // 请求头 Body io.ReadCloser // 请求体 ContentLength int64 // 请求体长度 Host string // 目标主机 Form url.Values // 表单参数 PostForm url.Values // POST 表单参数 MultipartForm *multipart.Form // 多部分表单 Trailer Header // 预期的尾随头 RemoteAddr string // 客户端地址 RequestURI string // 原始请求 URI // 其他字段省略 }
-
http.Response
http.Response
表示一个 HTTP 响应,包括状态码、头部、主体等。
type Response struct { Status string // 状态描述 StatusCode int // 状态码 Proto string // HTTP 协议版本 Header Header // 响应头 Body io.ReadCloser// 响应体 ContentLength int64 // 响应体长度 TransferEncoding []string // 传输编码 Uncompressed bool // 内容是否未压缩 Trailer Header // 尾随头 Request *Request // 关联的请求 // 其他字段省略 }
-
http.Header
http.Header
是一个用于表示 HTTP 头部的 map,其中键和值都是字符串。
type Header map[string][]string
- 用于存储多值头部,比如
Set-Cookie
。
-
http.Handler
和http.HandlerFunc
http.Handler
是一个接口,用于处理 HTTP 请求。
type Handler interface { ServeHTTP(ResponseWriter, *Request) }
http.HandlerFunc
是一个适配器,用于让普通函数实现http.Handler
接口。
type HandlerFunc func(ResponseWriter, *Request) func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) { f(w, r) }
-
http.ResponseWriter
http.ResponseWriter
是一个接口,用于构建 HTTP 响应。
type ResponseWriter interface { Header() Header Write([]byte) (int, error) WriteHeader(statusCode int) }
-
http.Client
http.Client
用于发起 HTTP 请求并接收响应。
type Client struct { Transport RoundTripper CheckRedirect func(req *Request, via []*Request) error Jar CookieJar Timeout time.Duration }
-
http.Server
http.Server
用于配置和运行 HTTP 服务器。
type Server struct { Addr string Handler Handler ReadTimeout time.Duration WriteTimeout time.Duration IdleTimeout time.Duration MaxHeaderBytes int TLSConfig *tls.Config // 其他字段省略 }
ht