来源于B站视频
课程视频
Web是基于http协议的一个服务,Go语言里面提供了一个完善的net/http包,通过http包可以很方便的就搭建起来一个可以运行的Web服务。
HandleFunc
文档简介
能够注册监听的路径pattern
并设置访问当前路径触发的回调方法.
func HandleFunc(pattern string, handler func(ResponseWriter, *Request))
HandleFunc registers the handler function for the given pattern in the DefaultServeMux. The documentation for ServeMux explains how patterns are matched.
ListenAndServe
文档简介
设置监听对应的主机和端口以及对应的处理方法.
第一个参数为网络地址,如果为"",则指的是所有网络接口的80端口.
第二个参数为Handler,如果传入nil
,则就是 DefaultServeMux
(可以看作是路由器)
func ListenAndServe(addr string, handler Handler) error
ListenAndServe listens on the TCP network address addr and then calls Serve with handler to handle requests on incoming connections. Accepted connections are configured to enable TCP keep-alives.
The handler is typically nil, in which case the DefaultServeMux is used.
ListenAndServe always returns a non-nil error.
案例能够监听localhost:8888并在页面中打印 Hello, World!
package main
import "net/http"
func main() {
http.HandleFunc("/", func(rw http.ResponseWriter, r *http.Request) {
rw.Write([]byte("Hello, World!"))
})
http.ListenAndServe("localhost:8888", nil) // DefaultServeMux
}
Go语言如何处理请求
http.ListenAndServe("localhost:8888", nil)
// 进入 ListenAndServe 源码部分
// 其实是创建了一个 server struct
// Addr表示网络的地址 Handler如果为nil则使用的DSM
func ListenAndServe(addr string, handler Handler) error {
server := &Server{
Addr: addr, Handler: handler}
return server.ListenAndServe()
}
第二种创建Web Server的方法:
尝试自己使用 server 来执行 ListenAndServe 操作
func main() {
server := http.Server{
Addr: "localhost:8888",
Handler: nil,
}
server.ListenAndServe()
}
Handler本质是一个interface
,里面定义了一个方法ServerHTTP()
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
那么前面提到的DefaultServeMux
是什么呢?
DefaultServeMux
是一个多路复用器,它也是一个Handler
源码证明
// DefaultServeMux 是 ServeMux 的指针
var DefaultServeMux = &defaultServeMux
var defaultServeMux ServeMux
// ServeMux 是什么呢? 继续看,发现是一个 struct
type ServeMux struct{
...// 省略}
// 如何说明一个 ServeMux 是一个 Handler 呢? 只需要实现 ServeHTTP 接口
func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request){
...}
本节案例:
自定义一个handler
,然后处理请求
package main
import "net/http"
type myHandler struct{
}
func (m *myHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello,IceBear!"))
}
func main() {
mh := myHandler{
}
// http.ListenAndServe("localhost:8888", nil)
server := http.Server{
Addr: "localhost:8888",
Handler: &mh,
}
server.ListenAndServe()
}
这一节主要讲解两个函数:Handle
和HandleFunc
如何处理多个handler
呢?
首先,不指定 Server struct 里面的 Handler 字段,可以通过http.Handle
将某个Handler附加到DefaultServeMux
http.Handle
func Handle(pattern string, handler Handler)
Handle registers the handler for the given pattern in the DefaultServeMux. The documentation for ServeMux explains how patterns are matched.
实际上,ServeMux struct中也有一个 Handle
方法
如果调用 http.Handle
,实际上调用的是DefaultServeMux上的Handle
方法.
案例:如何向DefaultServeMux注册Handler
package main
import "net/http"
type myHandler struct{
}
func (m *myHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello,IceBear!"))
}
type aboutHandler struct{
}
func (m *aboutHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello,About!"))
}
func main() {
mh := myHandler{
}
ah := aboutHandler{
}
// http.ListenAndServe("localhost:8888", nil)
server := http.Server{
Addr: "localhost:8888",
Handler: nil,
}
http.Handle("/hello", &mh)
http.Handle("/about", &ah)
server.ListenAndServe()
}
http.HandleFunc
原理:
Go定义了一个函数类型HandlerFunc
,可以将具有适当函数签名的函数f
,适配成一个Handler
.
源码解析
func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
DefaultServeMux.HandleFunc(pattern, handler)
}
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
if handler == nil {
panic("http: nil handler")
}
mux.Handle(pattern, HandlerFunc(handler))
}
// 适配器,可以将具有对应函数类型的函数转换成为一个 Handler
type HandlerFunc func(ResponseWriter, *Request)
// ServeHTTP calls f(w, r).
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}
案例:使用HandleFunc绑定Handler
package main
import "net/http"
func welcome(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Welcome!"))