Go怎么启动web服务?

102 阅读2分钟

启动web服务非常简单,只需要使用http.HandleFunc(),http.ListenAndFunc()这两个函数就可以启动一个web服务了。

image.png

HandleFunc()

http.HandleFunc()底层会调用ServeMux.HandleFunc(), image.png

我们传进来的handler是一个函数,但是如果直接把handler传给mux.Handle()则会报错,因为handler没有实现Handler这个接口。实现Handler接口需要实现ServeHTTP(),所以对handler进行强制类型转换,转换成HandlerFunc类型,HandlerFunc实现了ServeHTTP()。 image.png image.png

现在看ServeMux.Handle(),从注释中可以看出Handle主要是给指定的pattern注册handler的, image.png

看看ServeMux,这个结构体中有m和es这两个存储handler的字段,当注册handler的时候,首先把handler注册进m这个map中,用来进行精确查找,之后判断pattern的最后一个字符是不是 '/' ,如果是 '/',加入es中。

image.png

ListenAndServe()

当调用ListenAndServe()时,传入的handler是nil,然后会调用net.Listen()监听端口;在Server.Serve()的for循环中对于每一个请求都会起一个协程进行处理。 image.png

在conn.serve()中调用conn.readRequest()从连接中读取请求,然后调用serverHandler.ServeHTTP(), image.png

在serverHandler.ServeHTTP()中,首先判断handler是否为nil,因为我们在调用ListenAndServe()时,传入的handler是nil,所以这里handler为DefaultServeMux。DefaultServeMux的类型为 *ServeMux , image.png image.png

当执行handler.ServeHTTP()时,真正调用的是ServeMux.ServeHTTP(); image.png

ServeMux.ServeHTTP()中mux.Handler()会返回一个handler来处理该请求,会根据传入的路径进行不同的操作。如果我们注册了/tree/的handler,没有注册/tree的handler,那么会redirect到/tree/。 image.png image.png

ServeMux.handler()中调用match()返回最匹配的handler,首先会从ServeMux.m中寻找,如果找到直接返回,否则在循环遍历es的过程中看path的前缀是否是pattern(es中的handler按照pattern的长度从长到短排序的)。 image.png image.png

找到了handler之后返回ServeMux.ServeHTTP()中调用h.ServeHTTP(w, r),这里的h其实是http.HandlerFunc,调用ServeHTTP()也就是调用我们自己注册的handler函数。 image.png