用go 来实现一个极简的web框架,框架虽然简单,但是里面也包括了核心内容,对需要学习web框架的人开说是一个不错的学习路径。简单的web框架主要包括端口监听,获取请求和路由响应。go里面本身带有http库来实现这些功能。第一天的代码主要分为两部分,1是main函数入口,2是框架部分。我们先看看main函数
func main() {
r := gee.New()
r.Get("/",func(w http.ResponseWriter,r* http.Request){
fmt.Fprintf(w, "URL.Path = %q\n", r.URL.Path)
})
r.Get("/hello", func(w http.ResponseWriter, req *http.Request) {
for k, v := range req.Header {
fmt.Fprintf(w, "Header[%q] = %q\n", k, v)
}
})
r.RUN(":9090")
}
main函数中主要是实例化一个gee框架,然后获取请求,最后是启动服务。从main函数中可以看出,我们的gee 结构体至少要绑定Get 方法,New 方法和RUN方法。gee结构体里面的参数应该是一个map,map 的key 是一个string,它是由请求方法和请求路径构成的字符串。对应的应该是操作逻辑。所以有了以上想法我们来设计gee。
type HandlerFunc func(http.ResponseWriter,*http.Request)
type Engine struct {
router map[string]HandlerFunc
}
func New()* Engine{
return &Engine{router:make(map[string]HandlerFunc)}
}
框架里面应该包含这三部分,其中HandlerFunc 对应操作逻辑,Engine是一个结构体,参数是一个router 它是一个由string 对应操作逻辑构成的路由。New函数返回指向Engine的指针。
我们首先要为Engine 类型绑定addRoute 方法,该方法主要是向Engine 里面的map 添加内容,map的key是由请求方法和URL构成的字符串,对应的是操作逻辑,请求方法一共由4种(get post ,put delete)。所以addRoute的原型应该是这样
func(engine *Engine)addRoute(method string,pattern string,handler HandlerFunc) {
key:=method+"-"+pattern
engine.router[key]=handler
}
有了addRoute方法,再来实现请求逻辑就简单了一些:
func(engine *Engine)Get(pattern string, handler HandlerFunc){
engine.addRoute("GET",pattern, handler)
}
func(engine *Engine)POST(pattern string, handler HandlerFunc) {
engine.addRoute("GET",pattern, handler)
}
关于如何启动服务,go 里面由简单的启动服务的函数http.ListenAndServe(addr,engine)
其中addr是服务地址,engine是分发路由,如果把engine 写为nil 那就会调用go默认的处理逻辑。所以run函数的原型应该是这样
func (engine *Engine)RUN(addr string)(err error){
return http.ListenAndServe(addr,engine)
}
给engine 结构体绑定RUN方法,其中传入地址,返回error。
除此之外,engine还要绑定ServeHTTP方法,只有这样,自定义的路由才能真正的成为web 服务器的后台。
func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
key := req.Method + "-" + req.URL.Path
if handler, ok := engine.router[key]; ok {
handler(w, req)
} else {
fmt.Fprintf(w, "404 NOT FOUND: %s\n", req.URL)
}
}
这段代码其实做了一下几件事情,第一:获取客户端的相应方法,然后得到Method 和URL 将他们组成字符串以后去map里面找对应的处理逻辑,如果找得到就调用处理逻辑handler,找不到就输出错误。关于handler的实现方法实际上是在mian函数里面实现的。
原项目地址:
https://github.com/geektutu/7days-golang
有疑问加站长微信联系(非本文作者)