package mainimport ("fmt""log""net/http")func IndexHandle(w http.ResponseWriter,r *http.Request){fmt.Fprintf(w,"path = %s\n",r.URL.Path)}func HelloHandle(w http.ResponseWriter,r *http.Request){fmt.Fprintf(w,"%v\n",r.Header)}func main() {http.HandleFunc("/",IndexHandle)http.HandleFunc("/hello",HelloHandle)log.Fatal(http.ListenAndServe(":8090",nil))}
/和/hello,分别绑定 indexHandler 和 helloHandler , 根据不同的HTTP请求会调用不同的处理函数。
ListenAndServe(addr string, handler Handler)
:8090表示在 8090 端口监听。而第二个参数是则代表处理所有的HTTP请求的实例,nil 代表使用标准库中的实例处理。
http.Handler
是一个接口
type Handler interface {ServeHTTP(ResponseWriter, *Request)}
上面的代码可以如下实现
package mainimport ("fmt""log""net/http")type Engine struct {}func (engine *Engine)ServeHTTP(w http.ResponseWriter, req *http.Request){switch req.URL.Path {case "/":fmt.Fprintf(w,"path = %s\n",req.URL.Path)case "/hello":fmt.Fprintf(w,"%v\n",req.Header)default:fmt.Fprintf(w,"404 NOT FOUND %s\n",req.URL.Path)}}func main() {log.Fatal(http.ListenAndServe(":8090",&Engine{}))}
实现一个简单的路由
package gunimport ("fmt""net/http")type Engine struct {router map[string] http.HandlerFunc}func New()*Engine{return &Engine{router: map[string]http.HandlerFunc{}}}func (engine *Engine)ServeHTTP(w http.ResponseWriter,r *http.Request){key := r.Method+"-"+r.URL.Pathif handle,ok:=engine.router[key];ok{handle(w,r)}else {fmt.Fprintf(w, "404 NOT FOUND: %s\n", r.URL.Path)}}func(engine *Engine)addRoute(method,path string, handler http.HandlerFunc){key := method+"-"+pathengine.router[key]= handler}func(engine *Engine)Get(path string, handler http.HandlerFunc){engine.addRoute("GET",path,handler)}func(engine *Engine)Post(path string, handler http.HandlerFunc){engine.addRoute("POST",path,handler)}func (engine *Engine)Run(addr string)error{return http.ListenAndServe(addr,engine)}
将上面的代码可以改成
package mainimport ("fmt""github.com/baxiang/go-note/http/gun""net/http")func IndexHandle(w http.ResponseWriter,r *http.Request){fmt.Fprintf(w,"path = %s\n",r.URL.Path)}func HelloHandle(w http.ResponseWriter,r *http.Request){fmt.Fprintf(w,"%v\n",r.Header)}func main() {r := gun.New()r.Get("/",IndexHandle)r.Get("/hello",HelloHandle)r.Run(":8090")}
json
package mainimport ("encoding/json""fmt""github.com/baxiang/go-note/http/gun""net/http")func IndexHandle(w http.ResponseWriter,r *http.Request){fmt.Fprintf(w,"path = %s\n",r.URL.Path)}func HelloHandle(w http.ResponseWriter,r *http.Request){w.Header().Set("Content-Type","application/json")w.WriteHeader(http.StatusOK)encoder := json.NewEncoder(w)if err :=encoder.Encode(map[string]interface{}{"hello":"world"});err!=nil{http.Error(w,err.Error(),http.StatusInternalServerError)}}func main() {r := gun.New()r.Get("/",IndexHandle)r.Get("/hello",HelloHandle)r.Run(":8090")}
Context
请求上下文的封装
package gunimport ("encoding/json""net/http""fmt")type H map[string]interface{}type Context struct {Writer http.ResponseWriterReq *http.RequestPath stringMethod stringStatusCode int}func NewContext(w http.ResponseWriter,req *http.Request)*Context{return &Context{Writer: w,Req: req,Path: req.URL.Path,Method: req.Method,}}func(c *Context)SetHeader(key,value string){c.Writer.Header().Set(key,value)}func (c *Context)SetStatusCode(statusCode int){c.StatusCode = statusCodec.Writer.WriteHeader(statusCode)}func(c *Context)JSON(statusCode int,obj interface{}){c.SetHeader("Content-Type","application/json")c.SetStatusCode(statusCode)encoder := json.NewEncoder(c.Writer)if err :=encoder.Encode(obj);err!=nil{http.Error(c.Writer, err.Error(), http.StatusInternalServerError)}}func (c *Context) String(statusCode int, format string, values ...interface{}) {c.SetHeader("Content-Type", "text/plain")c.SetStatusCode(statusCode)c.Writer.Write([]byte(fmt.Sprintf(format, values...)))}func (c *Context) HTML(SetStatusCode int, html string) {c.SetHeader("Content-Type", "text/html")c.SetStatusCode(SetStatusCode)c.Writer.Write([]byte(html))}
router
路由处理逻辑
package gunimport "net/http"type router struct {handlers map[string] HandlerFunc}func newRouter()*router{return &router{handlers: map[string]HandlerFunc{},}}func(r *router)addRouter(method,path string,handle HandlerFunc){key :=method+"-"+pathr.handlers[key] = handle}func(r *router)handle(c *Context){key :=c.Method+"-"+c.Pathif handler,ok :=r.handlers[key];ok{handler(c)}else {c.String(http.StatusNotFound, "404 NOT FOUND: %s\n", c.Path)}}
engine
package gunimport ("net/http")type HandlerFunc func(*Context)type Engine struct {router *router}func New()*Engine{return &Engine{router: newRouter()}}func (engine *Engine)ServeHTTP(w http.ResponseWriter,r *http.Request){c :=NewContext(w,r)engine.router.handle(c)}func(engine *Engine)addRoute(method,path string, handler HandlerFunc){engine.router.addRouter(method,path,handler)}func(engine *Engine)Get(path string, handler HandlerFunc){engine.addRoute("GET",path,handler)}func(engine *Engine)Post(path string, handler HandlerFunc){engine.addRoute("POST",path,handler)}func (engine *Engine)Run(addr string)error{return http.ListenAndServe(addr,engine)}
