经过对http包的分析以后,如今让咱们来梳理一下整个的代码执行过程。html
按顺序作了几件事:git
按顺序作了几件事情:github
mux.handler(r).ServeHTTP(w, r)golang
(1)调用http.HandleFunc(2)调用http.ListenAndServe(":8080", nil)web
(1)map[string]http.HandlerFunc格式,其中的string由method和传入参数拼接字符串组成(2)map[string]map[string]http.HandlerFunc,,其中一维的键String表示请求method好比post, get 等。二维的键string表示要匹配的URL地址, http.HandlerFunc固然就是处理URL请求的具体方法。segmentfault
//http.go package main import ( "fmt" "net/http" ) func main() { http.HandleFunc("/", SayhelloName) http.ListenAndServe(":8080", nil) } func SayhelloName(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "原生HTTP路由测试页面") } /* package main import ( "fmt" "log" "net/http" ) func main() { http.HandleFunc("/", SayhelloName) log.Fatal(http.ListenAndServe(":8080", nil)) //http.ListenAndServe(":8080", nil) } func SayhelloName(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "原生HTTP路由测试页面") } */
原生方式主要是2个操做,第1步使用http.HandleFunc函数导入对应的方法,第二步使用http.ListenAndServe监听对应的端口app
你能够直接使用&结构体方式new一个空对象,来实现:框架
//第一种方式 package main import ( "fmt" "net/http" ) type MyMux struct { } func (p *MyMux) ServeHTTP(w http.ResponseWriter, r *http.Request) { if r.URL.Path == "/" { sayhelloName(w, r) return } http.NotFound(w, r) return } func sayhelloName(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello MyMuxRoute!") } func main() { mux := &MyMux{} //&结构体方式 http.ListenAndServe(":8080", mux) //mux是核心操做代码 }
func NewMyMux() *MyMux { return new(MyMux) }
完整代码tcp
//第二种方式 package main import ( "fmt" "net/http" ) type MyMux struct { } func (p *MyMux) ServeHTTP(w http.ResponseWriter, r *http.Request) { if r.URL.Path == "/" { sayhelloName(w, r) return } http.NotFound(w, r) return } func sayhelloName(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello MyMuxRoute!") } //新建的&结构体方法,框架中十分经常使用 func NewMyMux() *MyMux { return &MyMux{} //等同于 return new(MyMux) } func main() { mux := NewMyMux() //经过调用一个方法来实现 http.ListenAndServe(":8080", mux) //mux是核心代码 }
//第二种方式代码封装 //03http.go package main import ( "GoHTTP/01httpBase/03httpBase/route" //你复制过去的代码,前面的HTTP/01httpBase/03httpBase/根据须要修改 "net/http" ) func main() { mux := route.NewMyMux() //经过调用一个方法来实现 http.ListenAndServe(":8080", mux) //mux是核心代码 }
封装的路由route.go代码:函数
//route包函数封装 //route.go package route import ( "fmt" "net/http" ) type MyMux struct { } //新建的&结构体方法,框架中十分经常使用 func NewMyMux() *MyMux { return &MyMux{} //等同于 return new(MyMux) } func sayhelloName(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello MyMuxRoute!") } func (p *MyMux) ServeHTTP(w http.ResponseWriter, r *http.Request) { //下面是路由处理,通常web框架会使用一个封装函数统一处理 if r.URL.Path == "/" { sayhelloName(w, r) //这是全部web框架路由的核心代码 return } http.NotFound(w, r) return }
//第二种方式代码封装 //增长NewMyMux结构体属性,方便存储http.HandleFunc("/", SayhelloName)路由规则 //04http.go package main import ( "GoHTTP/01httpBase/03httpBase/route" //你复制过去的代码,前面的HTTP/01httpBase/03httpBase/根据须要修改 "net/http" ) func main() { mux := route.NewMyMux() //经过调用一个方法来实现 http.ListenAndServe(":8080", mux) //mux是核心代码 }
route.go代码:
//route包函数封装 //route.go package route import ( "fmt" "net/http" ) /*【对比前代码】 type MyMux struct { } */ type MyMux struct { handlers map[string][]*Handler //用于存储http.HandleFunc("/", SayhelloName) 格式的路由规则 } type Handler struct { path string http.HandlerFunc } /*【对比前代码】 //新建的&结构体方法,框架中十分经常使用 func NewMyMux() *MyMux { return &MyMux{} //等同于 return new(MyMux) } */ func NewMyMux() *MyMux { return &MyMux{make(map[string][]*Handler)} } func sayhelloName(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello MyMuxRoute!") } func (p *MyMux) ServeHTTP(w http.ResponseWriter, r *http.Request) { //下面是路由处理,通常web框架会使用一个封装函数统一处理 if r.URL.Path == "/" { sayhelloName(w, r) //这是全部web框架路由的核心代码 return } http.NotFound(w, r) return }
//第二种方式代码封装 //封装http.ListenAndServe(":8080", mux)功能 //05http.go package main import ( "GoHTTP/01httpBase/05httpBase/route" //你复制过去的代码,前面的HTTP/01httpBase/03httpBase/根据须要修改 //"fmt" //"net/http" ) func main() { mux := route.NewMyMux() //经过调用一个方法来实现 mux.Listen(":8080") //http.ListenAndServe(":8080", mux) }
route.go代码详情:
//route包函数封装 //route.go package route import ( "fmt" "log" "net/http" ) type MyMux struct { handlers map[string][]*Handler //用于存储http.HandleFunc("/", SayhelloName) 格式的路由规则 } type Handler struct { path string http.HandlerFunc } //开启http服务 func (m *MyMux) Listen(port string) { err := http.ListenAndServe(port, m) if err != nil { log.Fatal("开启http服务错误!") } } func NewMyMux() *MyMux { return &MyMux{make(map[string][]*Handler)} } func (p *MyMux) ServeHTTP(w http.ResponseWriter, r *http.Request) { //下面是路由处理,通常web框架会使用一个封装函数统一处理 if r.URL.Path == "/" { sayhelloName(w, r) //这是全部web框架路由的核心代码 return } http.NotFound(w, r) return } func sayhelloName(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello MyMuxRoute!") }
//第二种方式代码封装 //封装AddRoute添加路由功能、重写ServeHTTP功能 //06http.go package main import ( "GoHTTP/01httpBase/06httpBase/route" //你复制过去的代码,前面的HTTP/01httpBase/03httpBase/根据须要修改 "fmt" "net/http" ) func main() { r := route.NewMyMux() //经过调用一个方法来实现 r.AddRoute("GET", "/", func(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "Hello Get!") }) //mux.Listen(":8080") http.ListenAndServe(":8080", r) }
//route包函数封装 //route.go package route import ( "fmt" "log" "net/http" "strings" ) type MyMux struct { handlers map[string][]*Handler //用于存储http.HandleFunc("/", SayhelloName) 格式的路由规则 } type Handler struct { path string http.HandlerFunc } //开启http服务 func (m *MyMux) Listen(port string) { err := http.ListenAndServe(port, m) if err != nil { log.Fatal("开启http服务错误!") } } func NewMyMux() *MyMux { return &MyMux{make(map[string][]*Handler)} } //添加路由 func (m *MyMux) AddRoute(mode string, path string, fun http.HandlerFunc) { m.add(mode, path, fun) } //添加路由 /*mode Post|Get|Put|Delete *path 前缀 *fun 方法 */ func (m *MyMux) add(mode, path string, fun http.HandlerFunc) { h := &Handler{ strings.ToLower(path), fun} //fmt调试代码能够删除 fmt.Println("h ::", &h) fmt.Println("strings.ToLower(path) ::", strings.ToLower(path)) fmt.Println("strings.ToLower(mode) ::", strings.ToLower(mode)) //下面是存储路由的核心代码,这里的路由m.handlers存储的格式是Get|Post|Put|Delete:String:http.HandlerFunc m.handlers[strings.ToLower(mode)] = append( m.handlers[strings.ToLower(mode)], h, ) fmt.Println("m.handlers", m.handlers[strings.ToLower(mode)]) } //优化前代码 /* func (p *MyMux) ServeHTTP2(w http.ResponseWriter, r *http.Request) { //下面是路由处理,通常web框架会使用一个封装函数统一处理 if r.URL.Path == "/" { sayhelloName(w, r) //这是全部web框架路由的核心代码 return } http.NotFound(w, r) return } */ //进行路由分配 func (m *MyMux) ServeHTTP(w http.ResponseWriter, r *http.Request) { //处理静态文件 url := strings.Split(strings.TrimLeft(r.URL.Path, "/"), "/") //调试代码,能够直接删除 fmt.Println("r", fmt.Sprintf("%+v", r)) fmt.Println("w", fmt.Sprintf("%+v", w)) for _, handler := range m.handlers[strings.ToLower(r.Method)] { if handler.path == "/"+strings.ToLower(url[0]) { handler.ServeHTTP(w, r) //调用的是func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) { f(w, r) } return } } http.NotFound(w, r) return }