Golang之http server

快来打我* 2021-09-03 05:21 463阅读 0赞

基于HTTP构建的网络应用包括两个端,即客户端(Client)和服务端(Server)。两个端的交互行为包括从客户端发出request、服务端接受request进行处理并返回response以及客户端处理response。所以http服务器的工作就在于如何接受来自客户端的request,并向客户端返回respond。
典型的http服务端处理流程:
服务器在接收到请求时,首先会进入路由(router),这是一个Multiplexer,路由的工作在于为这个request找到对应的处理器(handler),处理器对request进行处理,并构建response。GOlang实现的http server同样遵循这样的处理流程

http server实现一

  1. package main
  2. import (
  3. "fmt"
  4. "net/http"
  5. )
  6. func indexHandler(w http.ResponseWriter, r *http.Request) {
  7. fmt.Fprintf(w, "hello world")
  8. }
  9. func main() {
  10. http.HandleFunc("/", indexHandler)
  11. http.ListenAndServe(":8000", nil)
  12. }

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

http server 实现方式之二

  1. package main
  2. import (
  3. "fmt"
  4. "net/http"
  5. )
  6. type indexHandler struct {
  7. content string
  8. }
  9. func (ih *indexHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  10. fmt.Fprintf(w, ih.content)
  11. }
  12. func main() {
  13. http.Handle("/", &indexHandler{ content: "hello world!"})
  14. http.ListenAndServe(":8001", nil)
  15. }

在这里插入图片描述
发现并没有进入监听状态,可能是端口被占用了
筛选8001端口的进程 netstat -ano |findstr “8001”
在这里插入图片描述
强制(/F参数)杀死 pid 为 9088 的所有进程包括子进程(/T参数):

taskkill /T /F /PID 592
在这里插入图片描述
再次运行 发现可以了 进入监听状态
在这里插入图片描述
Go实现的http服务步骤,首先注册路由,然后创建服务并开启监听即可。下文我们将从注册路由、开启服务、处理请求这几个步骤了解Golang如何实现http服务

注册路由

http.HandleFunc和http.Handle都是用于注册路由,可以发现两者的区别在于第二个参数,前者是一个具有func(w http.ResponseWriter,r *http.Request)签名的函数,而后者是一个结构体,该结构体实现了func(w http.ResponseWriter ,r **http.Requests)签名的方法。
http.HandleFunc和http.Handle的源码如下:`

  1. func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
  2. DefaultServeMux.HandleFunc(pattern, handler)
  3. }
  4. //HandleFunc registers the handler function for the given pattern
  5. func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
  6. if handler == nil {
  7. panic("http: nil handler")
  8. }
  9. mux.Handle(pattern, HandlerFunc(handler))
  10. }
  11. func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
  12. if handler == nil {
  13. panic("http: nil handler")
  14. }
  15. mux.Handle(pattern, HandlerFunc(handler))
  16. }

可以看到这两个函数 最总都由DefaultServeMux调用Handle方法来完成路由的注册。
这里我们遇到两种类型的对象:ServeMux和Handler

Handler

handler是一个接口:

  1. type Handler interface{
  2. serveHTTP(ResponseWriter, *Request)
  3. }

Handler接口种声明了名为ServeHTTP的函数签名,也就是说任何结构只要实现了这个ServeHTTP方法,那么这个结构体就是一个Handler对象,其实go的http服务都是基于Handler进行处理,而Handler对象的ServeHTTP方法也正是用以处理request并构建response的核心逻辑所在。

回到上面的HandlerFunc函数,注意一下这行代码:

  1. mux.Handle(pattern,HandleFunc(handler))

可能有人会误认为HandleFunc是一个函数,包装了传入handler函数,返回了一个Handler对象。然而这里HandlerFunc实际上是将handler函数做了一个类型转换,看下HandlerFunc的定义:

  1. type HandlerFunc func(ResponseWriter,*Request)
  2. //ServeHTTP call f(w,r)
  3. func(f HandlerFunc) ServerHTTP(w ResponseWriter,r *Request){
  4. f(w,r)
  5. }

HandlerFunc是一个类型,只不过表示的是一个具有func(ResponseWriter, *Request)签名的函数类型,并且这种类型实现了ServeHTTP方法(在ServeHTTP方法中又调用了自身),也就是说这个函数其实就是一个Handler类型的对象,利用这种类型转换,我们可以将一个handler函数转换为一个Handler对象,而不需要定义一个结构体,再让这个结构体实现ServeHTTP方法

发表评论

表情:
评论列表 (有 0 条评论,463人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Golanghttp server

    基于HTTP构建的网络应用包括两个端,即客户端(Client)和服务端(Server)。两个端的交互行为包括从客户端发出request、服务端接受request进行处理并返回r