赞
踩
https://geektutu.com/post/gee-day3.html
仅仅是一个笔记,在此对geektutu大神膜拜
package main import ( "fmt" "log" "net/http" ) func main() { http.HandleFunc("/", indexHandler) http.HandleFunc("/hello", helloHandler) log.Fatal(http.ListenAndServe(":9999", nil)) //log.Fatal用来检测错误,如果出现了错误,就会调用log.Fatal函数来记录错误并终止程序执行 //第二个参数为nil,说明使用默认的路由器 } // handler echoes r.URL.Path func indexHandler(w http.ResponseWriter, req *http.Request) { fmt.Fprintf(w, "URL.Path = %q\n", req.URL.Path) } // handler echoes r.URL.Header func helloHandler(w http.ResponseWriter, req *http.Request) { for k, v := range req.Header { fmt.Fprintf(w, "Header[%q] = %q\n", k, v) }
用curl这个工具测试
$ curl http://localhost:9999/
URL.Path = "/"
$ curl http://localhost:9999/hello
Header["Accept"] = ["*/*"]
Header["User-Agent"] = ["curl/7.54.0"]
首先我们来解释一下curl
curl是一个命令行工具和库,用于在各种网络协议下传输数据,支持多种数据
curl可以通过URL从服务器下载或上传数据,具有许多功能
package main import ( "fmt" "log" "net/http" ) // Engine is the uni handler for all requests type Engine struct{} func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) { switch req.URL.Path { case "/": fmt.Fprintf(w, "URL.Path = %q\n", req.URL.Path) case "/hello": for k, v := range req.Header { fmt.Fprintf(w, "Header[%q] = %q\n", k, v) } default: fmt.Fprintf(w, "404 NOT FOUND: %s\n", req.URL) } } func main() { engine := new(Engine) log.Fatal(http.ListenAndServe(":9999", engine)) }
注意,我们现在已经自己实现了ServeHTTP,有了自己的处理思维了,而不在需要按照之前系统默认的那样,还需要创建一个处理程序,但是我们也不可能将所有的处理函数都放在ServeHTTP中,这个时候,我们需要沿着如何更好的回应系统中的请求的方向继续设计
观察源码:
package http
type Handler interface {
ServeHTTP(w ResponseWriter, r *Request)
}
func ListenAndServe(address string, h Handler) error
我们主要观察ListenAndServe的第二个参数,Handler是一个接口,也就是说只要实现了ServeHTTP就能传入Handler,所有的HTTP请求也就交给这个
我首先是实现了gee.go
没错,我们在是实现ServeHTTP函数的基础上,将这个函数变成了一个类型map[stirng]HandlerFunc ,并且将它命名为router进行封装
func main() { http.HandleFunc("/", indexHandler) http.HandleFunc("/hello", helloHandler) log.Fatal(http.ListenAndServe(":9999", nil)) //log.Fatal用来检测错误,如果出现了错误,就会调用log.Fatal函数来记录错误并终止程序执行 //第二个参数为nil,说明使用默认的路由器 } // handler echoes r.URL.Path func indexHandler(w http.ResponseWriter, req *http.Request) { fmt.Fprintf(w, "URL.Path = %q\n", req.URL.Path) } // handler echoes r.URL.Header func helloHandler(w http.ResponseWriter, req *http.Request) { for k, v := range req.Header { fmt.Fprintf(w, "Header[%q] = %q\n", k, v) }
猜测原始代码中,我们使用http.HandleFunc是让默认的路由处理器增添方法,我们也需要用一个函数来增添我们的方法,与这个类似
package gee import ( "fmt" "net/http" ) type HandlerFunc func(http.ResponseWriter, *http.Request) // Engine implement the interface of ServeHTTP type Engine struct { router map[string]HandlerFunc } // New is the constructor of gee.Engine func New() *Engine { return &Engine{router: make(map[string]HandlerFunc)} } func (engine *Engine) addRoute(method string, pattern string, handler HandlerFunc) { key := method + "-" + pattern engine.router[key] = handler } // GET defines the method to add GET request func (engine *Engine) GET(pattern string, handler HandlerFunc) { engine.addRoute("GET", pattern, handler) } // POST defines the method to add POST request func (engine *Engine) POST(pattern string, handler HandlerFunc) { engine.addRoute("POST", pattern, handler) } // Run defines the method to start a http server func (engine *Engine) Run(addr string) (err error) { return http.ListenAndServe(addr, engine) } func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) { key := req.Method + "-" + req.URL.Path if handler, ok := engine.router[key]; ok { /* 注意router是一个map结构 map[key]HandlerFunc if的目的是找到对应路径的处理器 */ handler(w, req) } else { fmt.Fprintf(w, "404 NOT FOUND:%s\n", req.URL) } }
知道我们为什么要设置请求方法吗,这个不是URL中的功能,
GET很容易在URL中看出,但是POST并不容易
这两者都是由服务器自动识别的,不是说我们在访问URL的时候,还去写一个POST和GET
然后发现引入包的时候引入不了,原来是要将go.mod和main.go在一起
原谅我前面学的太差了
package main import ( "example/gee" "fmt" "net/http" ) func main() { r := gee.New() r.GET("/", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "URL.Path = %q\n", r.URL.Path) }) r.GET("/hello", func(w http.ResponseWriter, r *http.Request) { for k, v := range r.Header { fmt.Fprintf(w, "Header[%q] = %q\n", k, v) } }) }
老老实实编写
package main import ( "example/gee" "fmt" "net/http" ) func main() { r := gee.New() r.GET("/", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "URL.Path = %q\n", r.URL.Path) }) r.GET("/hello", func(w http.ResponseWriter, r *http.Request) { for k, v := range r.Header { fmt.Fprintf(w, "Header[%q] = %q\n", k, v) } }) /* GET方法是用添加路由的 从源码中就能看到GET最终指向的其实是路由器 */ r.Run(":9999") }
接着我们用gitbash将这个day1的实验结束
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。