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