Go语言中处理 HTTP 服务器

服务器
DefaultServerMux 是 http.ServeMux 类型的一个默认实例,ServeMux 就是路由。其主要结构是一个映射 map,用来存储 URL 模式和相关处理函数的关系。参看源码可以看出来:

 1 概述

包 net/http 提供了HTTP服务器端和客户端的实现。本文说明关于服务器端的部分。

快速开始:

  1. package main 
  2.  
  3. import ( 
  4.   "log" 
  5.   "net/http" 
  6.  
  7. func main() { 
  8.   // 设置 路由 
  9.   http.HandleFunc("/", IndexAction) 
  10.  
  11.   // 开启监听 
  12.   log.Fatal(http.ListenAndServe(":8888", nil)) 
  13.  
  14. func IndexAction(w http.ResponseWriter, r *http.Request) { 
  15.   w.Write([]byte(`<h1 align="center">来自小韩说课的问候</h1>`)) 

运行程序,在浏览器上请求: localhost:8888,你会看到我们的结果:

Go语言构建HTTP服务器还是很容易的。深入说明。

[[252115]]

2 http.Server 类型

HTTP 服务器在 Go 语言中是由 http.Server 结构体对象实现的。参考 http.ListenAndServe()的实现:

  1. // 文件:src/net/http/server.go 
  2.  
  3. // ListenAndServe always returns a non-nil error. 
  4. func ListenAndServe(addr string, handler Handler) error { 
  5.   server := &Server{Addr: addr, Handler: handler} 
  6.   return server.ListenAndServe() 

可见过程是先实例化 Server 对象,再完成 ListenAndServe 。其中 Serve 对象就是表示 HTTP 服务器的对象。其结构如下:

  1. // 文件:src/net/http/server.go 
  2.  
  3. type Server struct { 
  4.   Addr    string  // TCP 监听地址, 留空为:":http" 
  5.   Handler Handler // 调用的 handler(路由处理器), 设为 nil 表示 http.DefaultServeMux 
  6.  
  7.   TLSConfig *tls.Config // TLS 配置对象 
  8.   ReadTimeout time.Duration // 请求超时时长 
  9.   ReadHeaderTimeout time.Duration // 请求头超时时长 
  10.   WriteTimeout time.Duration // 响应超时时长 
  11.   IdleTimeout time.Duration // 请求空闲时长(keep-alive下两个请求间) 
  12.   MaxHeaderBytes int // 请求头的最大长度 
  13.   TLSNextProto map[string]func(*Server, *tls.Conn, Handler) // NPN 型协议升级出现时接管TLS连接的处理器函数映射表 
  14.   ConnState func(net.Conn, ConnState) // 状态转换事件处理器 
  15.   ErrorLog *log.Logger // 日志记录对象 
  16.   disableKeepAlives int32     // accessed atomically. 
  17.   inShutdown        int32     // accessed atomically (non-zero means we're in Shutdown) 
  18.   nextProtoOnce     sync.Once // guards setupHTTP2_* init 
  19.   nextProtoErr      error     // result of http2.ConfigureServer if used 
  20.   mu         sync.Mutex 
  21.   listeners  map[*net.Listener]struct{} 
  22.   activeConn map[*conn]struct{} 
  23.   doneChan   chan struct{} 
  24.   onShutdown []func() 

可见 Server 定义了服务器需要的信息。

实例化了 Server 对象后,调用其 (srv *Server) ListenAndServe() error 方法。该方法会监听 srv.Addr 指定的 TCP 地址,并通过 (srv *Server) Serve(l net.Listener) error 方法接收浏览器端连接请求。Serve 方法会接收监听器 l 收到的每一个连接,并为每一个连接创建一个新的服务进程。

该 go 进程会读取请求,然后调用 srv.Handler 处理并响应。srv.Handler 通常会是 nil,这意味着需要调用 http.DefaultServeMux 来处理请求,这个 DefaultServeMux 是默认的路由,我们使用 http.HandleFunc 就是在 http.DefaultServeMux 上注册方法。

3 http.DefaultServeMux 默认路由对象

看 Go 的源码,了解 http.HandleFunc():

  1. func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) { 
  2.   DefaultServeMux.HandleFunc(pattern, handler) 

可以看出来,注册的函数被 DefaultServerMux 来使用了。注册的时候,需要 pattern,就是 URL 模式,以及处理该 URL 模式的函数。

DefaultServerMux 是 http.ServeMux 类型的一个默认实例,ServeMux 就是路由。其主要结构是一个映射 map,用来存储 URL 模式和相关处理函数的关系。参看源码可以看出来:

  1. type ServeMux struct { 
  2.   mu    sync.RWMutex 
  3.   m     map[string]muxEntry // 映射表 
  4.   hosts bool // whether any patterns contain hostnames 
  5. type muxEntry struct { 
  6.   h       Handler 
  7.   pattern string 

可以调用多次 http.HandleFunc() 来注册多个处理器。

URL 模式是固定的、由根开始的路径。处理器的 URL 模式匹配原则是 左侧长度优先匹配。

例如有模式 /path/article/ 和 /path/ ,如果请求的 URL 是 /path/other/ 会由 /path/ 注册的处理器来处理,而 URL 为 /path/article/42/ 会由 /path/article/ 来处理。

以斜杠结尾的模式代表一个由根开始的子树,就是以当前为前缀的都会匹配。因此 / 会匹配所有的未被其他注册的模式匹配的路径。

4 处理器

处理器可以由函数或实现 Handler 接口的对象来充当。Handler 接口就是要求对象实现和处理器函数一致的方法。看 http.Handler 接口的实现源码:

  1. type Handler interface { ServeHTTP(ResponseWriter, *Request)} 

我们使用函数 http.HandleFunc 注册处理函数,而使用 http.Handle 函数来注册满足 Handler接口的处理对象。效果是一致的。

服务器篇完,后续还有 请求对象,响应对象 。

责任编辑:武晓燕 来源: 韩忠康
相关推荐

2021-07-15 23:18:48

Go语言并发

2024-04-07 11:33:02

Go逃逸分析

2023-01-12 08:52:50

GoroutinesGo语言

2023-12-21 07:09:32

Go语言任务

2024-01-08 08:36:29

HTTPGo代理服务器

2017-11-10 08:58:49

Web服务器应用程序

2009-07-03 13:05:47

JSP HTTP服务器

2024-12-23 00:22:55

2023-01-31 08:48:49

Go语言文件

2024-04-01 00:02:56

Go语言代码

2021-06-08 07:45:44

Go语言优化

2022-07-19 12:25:29

Go

2023-01-30 15:41:10

Channel控制并发

2023-11-30 08:09:02

Go语言

2023-07-29 15:03:29

2019-07-04 15:00:32

PythonHTTP服务器

2018-01-19 10:30:48

HTTP服务器代码

2019-04-23 10:48:55

HTTPTomcat服务器

2009-07-06 17:56:12

JSP HTTP服务器

2019-08-22 15:26:24

HTTP服务器Python
点赞
收藏

51CTO技术栈公众号