Go语言中处理 HTTP 服务器

hanzkering · · 1813 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

## 1 概述 包 `net/http` 提供了HTTP服务器端和客户端的实现。本文说明关于服务器端的部分。 快速开始: ```go package main import ( "log" "net/http" ) func main() { // 设置 路由 http.HandleFunc("/", IndexAction) // 开启监听 log.Fatal(http.ListenAndServe(":8888", nil)) } func IndexAction(w http.ResponseWriter, r *http.Request) { w.Write([]byte(`<h1 align="center">来自小韩说课的问候</h1>`)) } ``` 运行程序,在浏览器上请求: `localhost:8888`,你会看到我们的结果: ![第一个服务器程序](http://asset.hellokang.net/images/go/server-welcome.png) Go语言构建HTTP服务器还是很容易的。深入说明。 <!-- more --> ## 2 http.Server 类型 HTTP 服务器在 Go 语言中是由 `http.Server` 结构体对象实现的。参考 `http.ListenAndServe()` 的实现: ```go // 文件:src/net/http/server.go // ListenAndServe always returns a non-nil error. func ListenAndServe(addr string, handler Handler) error { server := &Server{Addr: addr, Handler: handler} return server.ListenAndServe() } ``` 可见过程是先实例化 `Server` 对象,再完成 `ListenAndServe` 。其中 `Serve` 对象就是表示 HTTP 服务器的对象。其结构如下 : ```go // 文件:src/net/http/server.go type Server struct { Addr string // TCP 监听地址, 留空为:":http" Handler Handler // 调用的 handler(路由处理器), 设为 nil 表示 http.DefaultServeMux TLSConfig *tls.Config // TLS 配置对象 ReadTimeout time.Duration // 请求超时时长 ReadHeaderTimeout time.Duration // 请求头超时时长 WriteTimeout time.Duration // 响应超时时长 IdleTimeout time.Duration // 请求空闲时长(keep-alive下两个请求间) MaxHeaderBytes int // 请求头的最大长度 TLSNextProto map[string]func(*Server, *tls.Conn, Handler) // NPN 型协议升级出现时接管TLS连接的处理器函数映射表 ConnState func(net.Conn, ConnState) // 状态转换事件处理器 ErrorLog *log.Logger // 日志记录对象 disableKeepAlives int32 // accessed atomically. inShutdown int32 // accessed atomically (non-zero means we're in Shutdown) nextProtoOnce sync.Once // guards setupHTTP2_* init nextProtoErr error // result of http2.ConfigureServer if used mu sync.Mutex listeners map[*net.Listener]struct{} activeConn map[*conn]struct{} doneChan chan struct{} 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(): ```go func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) { DefaultServeMux.HandleFunc(pattern, handler) } ``` 可以看出来,注册的函数被 `DefaultServerMux` 来使用了。注册的时候,需要 pattern,就是 URL 模式,以及处理该 URL 模式的函数。 `DefaultServerMux` 是 `http.ServeMux` 类型的一个默认实例,`ServeMux` 就是路由。其主要结构是一个映射 map,用来存储 URL 模式和相关处理函数的关系。参看源码可以看出来: ```go type ServeMux struct { mu sync.RWMutex m map[string]muxEntry // 映射表 hosts bool // whether any patterns contain hostnames } type muxEntry struct { h Handler pattern string } ``` 可以调用多次 `http.HandleFunc()` 来注册多个处理器。 URL 模式是固定的、由根开始的路径。处理器的 URL 模式匹配原则是 *左侧长度优先匹配*。 例如有模式 `/path/article/` 和 `/path/` ,如果请求的 URL 是 `/path/other/` 会由 `/path/` 注册的处理器来处理,而 URL 为 `/path/article/42/` 会由 `/path/article/` 来处理。 以斜杠结尾的模式代表一个由根开始的子树,就是以当前为前缀的都会匹配。因此 `/` 会匹配所有的未被其他注册的模式匹配的路径。 ## 4 处理器 处理器可以由函数或实现 `Handler` 接口的对象来充当。`Handler` 接口就是要求对象实现和处理器函数一致的方法。看 `http.Handler` 接口的实现源码: ```go type Handler interface { ServeHTTP(ResponseWriter, *Request) } ``` 我们使用函数 `http.HandleFunc` 注册处理函数,而使用 `http.Handle` 函数来注册满足 `Handler` 接口的处理对象。效果是一致的。 完! 原文出自:[小韩说课](http://www.hellokang.net/go/go-http-server/) 微信关注:小韩说课 ![小韩说课](http://www.hellokang.net/images/wechat_subscription.jpg)

有疑问加站长微信联系(非本文作者))

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1813 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传