四. 简化HTTP处理器

67 阅读1分钟

1.回顾

前面我们已经对SimpleWeb进行了改造,已经解决了原本SimpleWeb中ServeHttp中路由映射规则以及业务逻辑耦合在一起的问题,也方便了路由映射规则的扩展。

但是此处还存在一个问题,我们看下前面的例子

type HelloHandler struct {
}

func (handler *HelloHandler) ServeHttp(c *Conn, req *Request) {
   c.WriteData([]byte("hello"))
}

func main() {
   // 创建一个处理器
   router := SimpleWeb{routes: map[string]Handler{}}
   // 完成请求和处理器的映射关系
   router.SetRoute("/hello", &HelloHandler{})
   // 启动http服务器
   ListenAndServe(":8080", &router)
}

这里我们创建一个HTTP服务器,此处需要给/hello 的请求设置一个请求处理器,请求处理器需要实现Handler接口,此处需要定义一个结构体HelloHandler,由其实现Handler接口。

那我们想一下,如果现在有一百个不同的请求路径,那么此时就存在一百个请求处理器,那么是不是需要创建100个结构体,然后实现一百次该接口。

2.改进

首先,定义HandleFunc类型,函数也是能够作为一种类型,实现Handler接口

type HandleFunc func(conn *Conn, request *Request)
func (f HandleFunc) ServeHttp(c *Conn, r *Request) {
   f(c, r)
}

接着,修改前面例子中的HTTP服务器,此时不再需要定义结构体,直接编写业务逻辑函数,比如下面的HandlerHello,将其强制类型转换为HandleFunc类型。

因为HandleFunc类型已经实现了Handler接口,所以可以作为SetRoute的参数,完成路由匹配规则的注册。

func HandlerHello(c *Conn, req *Request) {
   c.WriteData([]byte("hello"))
}

func main() {
   router := SimpleWeb{routes: map[string]Handler{}}
   router.SetRoute("/hello", HandleFunc(HandlerHello))
   ListenAndServe(":8080", &router)
}

这样子就不需要每个HTTP处理器都去创建一个结构体,然后实现Handler接口。