因为创建一个处理器和多路复用器唯一需要做的就是实现ServeHTTP方法,所以通过自行创建多路复用器来代替net/http包中的ServeMux是完全可行的,并且目前市面上已经出现了很多第三方的多路复用器可供使用,比如,Gorilla Toolkit(www.go-rillatoolkit.org)就是一个非常优秀的第三方多路复用器包,它提供了muxpat这两个工作方式非常不同的多路复用器,而本节将要介绍的则是另一个高效的轻量级第三方多路复用器——HttpRouter

ServeMux的一个缺陷是无法使用变量实现URL模式匹配。虽然在浏览器请求/threads的时候,使用ServeMux可以很好地获取并显示论坛中的所有帖子,但如果浏览器请求的是/thread/123,那么要获取并显示论坛里面ID为123的帖子就会变得非常困难。程序必须对URL进行语法分析才能提取出URL当中的帖子ID。此外,因为受ServeMux实现URL模式匹配的方式所限,如果我们想要通过/thread/123/post/456这样的URL从ID为123的帖子中获取ID为456的回复,就必须在程序里面进行大量复杂的语法分析,并因此给程序带来额外的复杂度。

ServeMux不同,HttpRouter包并没有上面提到的这些限制。本节将对HttpRouter包最重要的一部分特性进行介绍,关于这个包的更详细的说明可以在它的文档页面里面看到:https://github.com/julienschmidt/httprouter。代码清单3-12展示了一个使用HttpRouter实现的服务器。

代码清单3-12 使用HttpRouter实现的服务器

package main

import(
    "fmt"
    "github.com/julienschmidt/httprouter"
    "net/http"
)

func hello(w http.ResponseWriter, r *http.Request, p httprouter.Params){
    fmt.Fprintf(w,"Hello, %s!\n" , p.ByName("name"))
}

func main(){
    mux := httprouter.New()
    mux.GET("/hello/:name", hello)

    server := http.Server{
        Addr: "127.0.0.1:8080",
        Handler: mux,
    }
    server.ListenAndServe()
}

这个程序中的大部分代码都和之前展示过的代码一样,只是涉及多路复用器的部分代码跟之前有所不同。在这段代码里,程序通过调用New函数来创建一个多路复用器:

mux := httprouter.New()

这个程序不再使用HandleFunc绑定处理器函数,而是直接把处理器函数与给定的HTTP方法进行绑定:

mux.GET("/hello/:name", hello)

这段代码会把给定URL的GET方法与hello处理器函数进行绑定,当浏览器向这个URL发送GET请求时,hello函数就会被调用,但如果浏览器向这个URL发送除GET请求之外的其他请求,hello函数则不会被调用。需要注意的是,被绑定的URL包含了具名参数(named parameter),这些具名参数会被URL中的具体值所代替,并且程序可以在处理器里面获取这些值。

跟之前的处理器函数相比,现在的hello处理器函数也发生了变化,它不再接受两个参数,而是接受3个参数。其中第三个参数Params就包含了之前提到的具名参数,具名参数的值可以在处理器内部通过ByName方法获取:

func hello(w http.ResponseWriter, r *http.Request, p httprouter.Params){
    fmt.Fprintf(w,"Hello, %s!\n" , p.ByName("name"))
}

程序的最后一个变化是它不再使用默认的DefaultServeMux,而是通过将HttpRouter传递给Server结构来使用这个多路复用器:

server := http.Server{
    Addr: "127.0.0.1:8080",  
    Handler: mux,
}

server.ListenAndServe()

现在,如果我们在终端上执行go build命令,那么编译器将返回一个错误:

$ go build
server.go:5:5: cannot find package "github.com/julienschmidt/httprouter" 
in  any of:    /usr/local/go/src/github.com/julienschmidt/httprouter (from $GOROOT)
    /Users/sausheong/gws/src/github.com/julienschmidt/httprouter (from $GOPATH)

出现这个错误的原因在于,我们虽然指定了HttpRouter库,但这个第三方库在我们的电脑上并不存在,得益于Go语言强大且易用的包管理系统,我们只需要执行以下命令就可以解决这个问题了:

$ go get github.com/julienschmidt/httprouter

在电脑连接了网络的情况下,这个命令会从HttpRouterGitHub主页上下载HttpRouter包的源代码,并将其存储到$GOPATH/src目录中。在此之后,当我们再次执行go build命令尝试编译代码清单3-12所示的服务器时,编译器就会导入HttpRouter的代码,并对整个服务器进行编译。

results matching ""

    No results matching ""