0%

Go http

  • http.Server
  • Handler 与 DefaultServeMux
  • http.Handle()
  • http.HandleFunc()

http 编程

简单demo:

1
2
3
4
5
6
7
8
9
10
package main

import "net/http"

func main () {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("hello world"))
})
http.ListenAndServe("localhost:8080", nil) // DefaultServeMux
}

http.Server

http.ListenAndServe()源码:

实际上,就是创建了一个结构体 http.Server ,然后调用 server 的ListenAndServe() 方法

因此,可以直接创建一个 http.Server 变量,然后调用该方法:

1
2
3
4
5
6
7
func main() {
server := http.Server {
Addr: "localhost:8080",
Handler: nil,
}
server.ListenAndServe()
}

不过,这样无法访问,因为没有配置路由

Handler 与 DefaultServeMux

如果 http.Server 中的 Handler: nil ,默认为 DefaultServeMux
http.Handler 是一个接口,匹配所有实现了 ServeHTTP() 方法的结构体

代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package main

import "net/http"

type myHandler struct {}

func (handler myHandler) ServeHTTP (write http.ResponseWriter, read *http.Request) {
write.Write([]byte("hello world"))
}

func main() {
handler := myHandler{}

server := http.Server {
Addr: "localhost:8080",
Handler: &handler,
}

server.ListenAndServe()
}

不过,直接指定 Handler 会导致所有请求都交给该 Handler ,下面有两种解决方法

方法一:http.Handle()

不指定 Handler,使用 http.Handle() 方法将某个 Handler 附加到 DefaultServeMux 中

DefaultServeMux 是一个 ServeMux 类型的指针,ServeMux 中有 Handle() 方法

使用 http.Handle() 方法将某个 Handler 附加到 DefaultServeMux 中,实际上就是在调用 DefaultServeMux 的 Handle() 方法

代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package main

import "net/http"

type helloHandler struct {}

func (handler helloHandler) ServeHTTP (write http.ResponseWriter, read *http.Request) {
write.Write([]byte("hello"))
}

type homeHandler struct {}

func (handler homeHandler) ServeHTTP (write http.ResponseWriter, read *http.Request) {
write.Write([]byte("home"))
}

func main() {
hello := helloHandler{}
home := homeHandler{}

server := http.Server {
Addr: "localhost:8080",
Handler: nil,
}

http.Handle("/hello", hello)
http.Handle("/home", home)
server.ListenAndServe()
}

方法二:http.HandleFunc()

使用 http.HandleFunc() 将具有适当签名的 Handler 方法注册到 DefaultServeMux 中(使用 DefaultServeMux.HandleFunc() )

其中, HandlerFunc(handler) 是将通过参数传递的 handler 方法 适配(转型)成 HandlerFunc ,而 HandlerFunc 是一个函数类型,只要参数和返回值相同,就可以转型成 HandlerFunc。而 HandlerFunc 实现了 Handler 接口 的 ServeHTTP() 方法。

也就是说,自定义的方法(与 HandlerFunc 有相同的参数)被转型成了 HandleFunc ,然后作为 Handler 被添加到了 DefaultServeMux 中(后续过程与方法一类似)

代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package main

import (
"log"
"net/http"
)

func hello(w http.ResponseWriter, read *http.Request) {
if _, err := w.Write([]byte("hello")); err != nil {
log.Println(err)
return
}
}

func main() {
server := http.Server {
Addr: "localhost:8080",
Handler: nil,
}

http.HandleFunc("/hello", hello)
http.HandleFunc("/about", func(w http.ResponseWriter, r *http.Request){
_, _ = w.Write([]byte("about"))
})

if err := server.ListenAndServe(); err != nil {
log.Println(err)
return
}
}

内置的Handler

  • NotFoundHandler
  • RedirectHandler
  • StripPrefix
  • TimeoutHandler
  • FileServer