go web 框架-day1

语言: CN / TW / HK

用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
分享到: