深入理解Golang之http server的实现

2020-01-28 14:26:07王旭

前言

对于Golang来说,实现一个简单的 http server 非常容易,只需要短短几行代码。同时有了协程的加持,Go实现的 http server 能够取得非常优秀的性能。这篇文章将会对go标准库 net/http 实现http服务的原理进行较为深入的探究,以此来学习了解网络编程的常见范式以及设计思路。

HTTP服务

基于HTTP构建的网络应用包括两个端,即客户端( Client )和服务端( Server )。两个端的交互行为包括从客户端发出 request 、服务端接受 request 进行处理并返回 response 以及客户端处理 response 。所以http服务器的工作就在于如何接受来自客户端的 request ,并向客户端返回 response

典型的http服务端的处理流程可以用下图表示:

服务器在接收到请求时,首先会进入路由( router ),这是一个 Multiplexer ,路由的工作在于为这个 request 找到对应的处理器( handler ),处理器对 request 进行处理,并构建 response 。Golang实现的 http server 同样遵循这样的处理流程。

我们先看看Golang如何实现一个简单的 http server


package main

import (
 "fmt"
 "net/http"
)

func indexHandler(w http.ResponseWriter, r *http.Request) {
 fmt.Fprintf(w, "hello world")
}

func main() {
 http.HandleFunc("/", indexHandler)
 http.ListenAndServe(":8000", nil)
}

运行代码之后,在浏览器中打开 localhost:8000 就可以看到 hello world 。这段代码先利用 http.HandleFunc 在根路由 / 上注册了一个 indexHandler , 然后利用 http.ListenAndServe 开启监听。当有请求过来时,则根据路由执行对应的 handler 函数。

我们再来看一下另外一种常见的 http server 实现方式:


package main

import (
 "fmt"
 "net/http"
)

type indexHandler struct {
 content string
}

func (ih *indexHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 fmt.Fprintf(w, ih.content)
}

func main() {
 http.Handle("/", &indexHandler{content: "hello world!"})
 http.ListenAndServe(":8001", nil)
}

Go实现的 http 服务步骤非常简单,首先注册路由,然后创建服务并开启监听即可。下文我们将从注册路由、开启服务、处理请求这几个步骤了解Golang如何实现 http 服务。

注册路由

http.HandleFunchttp.Handle 都是用于注册路由,可以发现两者的区别在于第二个参数,前者是一个具有