package main
import (
"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 main
import (
"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 gun
import (
"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.Path
if 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+"-"+path
engine.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 main
import (
"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 main
import (
"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 gun
import (
"encoding/json"
"net/http"
"fmt"
)
type H map[string]interface{}
type Context struct {
Writer http.ResponseWriter
Req *http.Request
Path string
Method string
StatusCode 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 = statusCode
c.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 gun
import "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+"-"+path
r.handlers[key] = handle
}
func(r *router)handle(c *Context){
key :=c.Method+"-"+c.Path
if handler,ok :=r.handlers[key];ok{
handler(c)
}else {
c.String(http.StatusNotFound, "404 NOT FOUND: %s\n", c.Path)
}
}
engine
package gun
import (
"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)
}