方法绑定 | 参考官方实现
http.HandleFunc | go官方文档
-
会传入两个参数 | 匹配模式和处理方法 然后交给
DefaultServeMux的HandleFunc函数来实现模式匹配处理 -
其中这个
DefaultServeMux是go官方实现的 需要我们自己进行重现一下// HandleFunc registers the handler function for the given pattern // in the DefaultServeMux. // The documentation for ServeMux explains how patterns are matched. func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) { DefaultServeMux.HandleFunc(pattern, handler) } -
其中我们对于
DefaultServeMux结构体进行识别 会发现他的原始是type ServeMux struct { mu sync.RWMutex m map[string]muxEntry es []muxEntry // slice of entries sorted from longest to shortest. hosts bool // whether any patterns contain hostnames } type muxEntry struct { h Handler pattern string } // DefaultServeMux is the default ServeMux used by Serve. var DefaultServeMux = &defaultServeMux var defaultServeMux ServeMux -
我们自己可以仿照
go文档自己实现一个类似的方法// 处理函数 type HandleFunc func(http.ResponseWriter, *http.Request) // 官方实现的 比较全面 <-自己来手动写一个 基础的 //type ServeMux struct { // mu sync.RWMutex // m map[string]muxEntry // es []muxEntry // slice of entries sorted from longest to shortest. // hosts bool // whether any patterns contain hostnames //} // //type muxEntry struct { // h Handler // pattern string //} type Engine struct { router map[string]HandleFunc } func New() *Engine { return &Engine{router: make(map[string]HandleFunc)} } // 内部使用的 func (engine *Engine) addRounte(method string, pattern string, handler HandleFunc) { key := method + "-" + pattern engine.router[key] = handler } // get方法实现 func (engine *Engine) GET(pattern string, handler HandleFunc) { engine.addRounte("GET", pattern, handler) } // post方法实现 func (engine *Engine) POST(pattern string, handler HandleFunc) { engine.addRounte("POST", pattern, handler) } // run 开始运行 func (engine *Engine) Run(addr string) (err error) { return http.ListenAndServe(addr, engine) }
ListenAndServe | 参数接口实现
-
查看
go官方文档,不难发现// ListenAndServe listens on the TCP network address addr and then calls // Serve with handler to handle requests on incoming connections. // Accepted connections are configured to enable TCP keep-alives. // // The handler is typically nil, in which case the DefaultServeMux is used. // // ListenAndServe always returns a non-nil error. func ListenAndServe(addr string, handler Handler) error { server := &Server{Addr: addr, Handler: handler} return server.ListenAndServe() } -
其中有一个参数是
handler类型是Handler.// A Handler responds to an HTTP request. // // ServeHTTP should write reply headers and data to the ResponseWriter // and then return. Returning signals that the request is finished; it // is not valid to use the ResponseWriter or read from the // Request.Body after or concurrently with the completion of the // ServeHTTP call. // // Depending on the HTTP client software, HTTP protocol version, and // any intermediaries between the client and the Go server, it may not // be possible to read from the Request.Body after writing to the // ResponseWriter. Cautious handlers should read the Request.Body // first, and then reply. // // Except for reading the body, handlers should not modify the // provided Request. // // If ServeHTTP panics, the server (the caller of ServeHTTP) assumes // that the effect of the panic was isolated to the active request. // It recovers the panic, logs a stack trace to the server error log, // and either closes the network connection or sends an HTTP/2 // RST_STREAM, depending on the HTTP protocol. To abort a handler so // the client sees an interrupted response but the server doesn't log // an error, panic with the value ErrAbortHandler. type Handler interface { ServeHTTP(ResponseWriter, *Request) } -
而这是一个
interface类型的 需要我们来实现其中的方法ServeHTTP,其中官方文档中的一个实现方式是// ServeHTTP dispatches the request to the handler whose // pattern most closely matches the request URL. func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) { if r.RequestURI == "*" { if r.ProtoAtLeast(1, 1) { w.Header().Set("Connection", "close") } w.WriteHeader(StatusBadRequest) return } h, _ := mux.Handler(r) h.ServeHTTP(w, r) } -
我们为了达到自己实现目的,进行简单的类型匹配~(可以直接简化实现)
func (engine *Engine) ServeHTTP(w http.ResponseWriter, r *http.Request) { switch r.URL.Path { case "/": fmt.Fprintf(w, "URL.Path = %q\n", r.URL.Path) case "/hello": for k, v := range r.Header { fmt.Fprintf(w, "Header[%q] = %q\n", k, v) } default: fmt.Fprintf(w, "404 NOT FOUND: %s \n", r.URL) } }
区别对待参考 | 系统 + 自己 | 完整代码!
原本
//main.go
// main.go
package main
import (
"fmt"
"log"
"net/http"
)
func main() {
http.HandleFunc("/", indexHandler)
http.HandleFunc("/hello", helloHandler)
log.Fatal(http.ListenAndServe(":9999", nil))
}
// indexHandler
func indexHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "URL.Path ==%q\n", r.URL.Path)
}
// hellohandler
func helloHandler(w http.ResponseWriter, r *http.Request) {
for k, v := range r.Header {
fmt.Fprintf(w, "Header[%q] = %q\n", k, v)
}
}
自己实现
// base3/main.go
// base3/main.go
package main
import (
"fmt"
"net/http"
"yasuo" // 自己写的模块
)
func main() {
r := yasuo.New()
r.GET("/", indexHandler)
r.GET("/hello", helloHandler)
r.Run(":9999")
}
// indexHandler 此处为空函数也是可以 因为匹配结果处理 ServeHTTP 已经实现
func indexHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "URL.Path ==%q\n", r.URL.Path)
}
// hellohandler 理由同上!
func helloHandler(w http.ResponseWriter, r *http.Request) {
for k, v := range r.Header {
fmt.Fprintf(w, "Header[%q] = %q\n", k, v)
}
}
// base3/yasuo/yasuo.go
// base3/yasuo/yasuo.go
package yasuo
import (
"fmt"
"net/http"
)
// 处理函数
type HandleFunc func(http.ResponseWriter, *http.Request)
// 官方实现的 比较全面 <-自己来手动写一个 基础的
//type ServeMux struct {
// mu sync.RWMutex
// m map[string]muxEntry
// es []muxEntry // slice of entries sorted from longest to shortest.
// hosts bool // whether any patterns contain hostnames
//}
//type muxEntry struct {
// h Handler
// pattern string
//}
type Engine struct {
router map[string]HandleFunc
}
func New() *Engine {
return &Engine{router: make(map[string]HandleFunc)}
}
// 内部使用的
func (engine *Engine) addRounte(method string, pattern string, handler HandleFunc) {
key := method + "-" + pattern
engine.router[key] = handler
}
// get方法实现
func (engine *Engine) GET(pattern string, handler HandleFunc) {
engine.addRounte("GET", pattern, handler)
}
// post方法实现
func (engine *Engine) POST(pattern string, handler HandleFunc) {
engine.addRounte("POST", pattern, handler)
}
// run 开始运行
func (engine *Engine) Run(addr string) (err error) {
return http.ListenAndServe(addr, engine)
}
// 因为 http.ListenAndServe 第二个参数是 handle是一个接口 接口实现了ServeHTTP
// 需要我们自己来实现一下 ServeHTTP
//
// type Handler interface {
// ServeHTTP(ResponseWriter, *Request)
// }
func (engine *Engine) ServeHTTP(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case "/":
fmt.Fprintf(w, "URL.Path = %q\n", r.URL.Path)
case "/hello":
for k, v := range r.Header {
fmt.Fprintf(w, "Header[%q] = %q\n", k, v)
}
default:
fmt.Fprintf(w, "404 NOT FOUND: %s \n", r.URL)
}
mt := "GET" + "-" + r.URL.Path
fmt.Println(engine.router[r.URL.Path], mt, engine.router[mt])
}