下一篇 Go圣经-学习笔记之error接口github
package http type Handler interface{ ServeHTTP(w ResponseWriter, r *Request) } func ListenAndServe(address string, h Handler) error
经过运行指定的服务端口,把全部该端口的客户端请求所有转发给h作分发处理,Go圣经举了一个获取各个商品价格的例子:golang
func main() { db := database{"shoes": 50, "socks": 5} log.Fatal(http.ListenAndServe("localhost:8000", db)) } type dollars float32 func (d dollars) String() string { return fmt.Sprintf("$%.2f", d) } type database map[string]dollars func (db database) ServeHTTP(w http.ResponseWriter, req *http.Request) { for item, price := range db { fmt.Fprintf(w, "%s: %s\n", item, price) } }
因此,若是咱们要设计一个web服务的路由框架,则就是经过隐式实现ServeHTTP接口作的,通常作法:首先创建好路由树或者路由表,而后启动服务,当一个请求到达服务端后,首先经过ServeHTTP处理客户端的路由是否在路由树或者路由表中存在,若是不存在,直接报404页面没发现的错误。不然,由路由树分发后的api处理请求。例如:httprouter一个轻量级且高性能的路由请求框架。web
package main import ( "fmt" "github.com/julienschmidt/httprouter" "net/http" "log" ) func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { fmt.Fprint(w, "Welcome!\n") } func Hello(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { fmt.Fprintf(w, "hello, %s!\n", ps.ByName("name")) } func main() { router := httprouter.New() router.GET("/", Index) router.GET("/hello/:name", Hello) log.Fatal(http.ListenAndServe(":8080", router)) }
/
和/hello/:name
,;/
, 则有分发后的Index接口处理请求;/hello/:name
,则由分发后的Hello接口处理该请求;路由也支持正则表达式,主要看本身的设计了。入口为ServeHTTP路由分发。正则表达式
Go语言标准库http自带路由分发功能:api
mux:=http.NewServeMux() mux.Handle("/", http.HandlerFunc(Index)) mux.Handle("/hello/:name", http.HandlerFunc(Hello)) log.Fatal(http.ListenAndServe("localhost:8000", mux) // ServeMux实现了ServeHTTP方法 // 或者 http.HandleFunc("/", Index) // 内部有一个全局的ServeMux, 因此咱们通常不用上面的使用方法 http.HandleFunc("/hello/:name" Hello)
ServeMux是利用map[pattern]handler数据结构实现的,不支持正则路由,也就基本上不支持RESTful路由,推荐两个路由框架:数据结构
对于第一个路由,吐槽比较多的地方:1. 不更新;2.正则和非正则路由有冲突,能够看我提的issue;框架