經過對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 }