zoukankan      html  css  js  c++  java
  • gin 学习笔记

    gin

    http.handler

    接口定义

    package http
    
    type Handler interface {
        ServeHTTP(w ResponseWriter, r *Request)
    }
    
    func ListenAndServe(address string, h Handler) error
    

    ListenAndServe: 定义一个 http 服务器,监听 address 地址,使用 Handler 来 进行服务处理。
    Handler:接口,实现方法 ServeHTTP(w ResponseWriter, r *Request),用来执行 http 请求。

    gin 实现

    核心代码

    
    // demo
    func main() {
        //1 Default engine
    	router := gin.Default()
    
    	//2 add handler
    	router.POST("/loginJSON", func(c *gin.Context) {
    		var json Login
    		if err := c.ShouldBindJSON(&json); err != nil {
    			c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
    			return
    		}
    		
    		c.JSON(http.StatusOK, gin.H{"status": "you are logged in"})
        })
    
    	//3 Listen and serve on 0.0.0.0:8080
    	router.Run(":8080")
    }
    
    // Default returns an Engine instance with the Logger and Recovery middleware already attached.
    func Default() *Engine {
    	engine := New() // Engine 扩展 RouterGroup,实现 ServeHTTP
    	engine.Use(Logger(), Recovery())
    	return engine
    }
    
    func New() *Engine {
    	debugPrintWARNINGNew()
    	engine := &Engine{
    		RouterGroup: RouterGroup{
    			Handlers: nil,
    			basePath: "/",
    			root:     true,
    		},
    		FuncMap:                template.FuncMap{},
    		RedirectTrailingSlash:  true,
    		RedirectFixedPath:      false,
    		HandleMethodNotAllowed: false,
    		ForwardedByClientIP:    true,
    		AppEngine:              defaultAppEngine,
    		UseRawPath:             false,
    		RemoveExtraSlash:       false,
    		UnescapePathValues:     true,
    		MaxMultipartMemory:     defaultMultipartMemory,
    		trees:                  make(methodTrees, 0, 9),
    		delims:                 render.Delims{Left: "{{", Right: "}}"},
    		secureJSONPrefix:       "while(1);",
    	}
    	engine.RouterGroup.engine = engine
    	engine.pool.New = func() interface{} {
    		return engine.allocateContext()
    	}
    	return engine
    }
    
    // Run attaches the router to a http.Server and starts listening and serving HTTP requests.
    // It is a shortcut for http.ListenAndServe(addr, router)
    // Note: this method will block the calling goroutine indefinitely unless an error happens.
    func (engine *Engine) Run(addr ...string) (err error) {
    	defer func() { debugPrintError(err) }()
    
    	address := resolveAddress(addr)
    	debugPrint("Listening and serving HTTP on %s
    ", address)
    	err = http.ListenAndServe(address, engine)
    	return
    }
    
    // ServeHTTP conforms to the http.Handler interface.
    func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
    	c := engine.pool.Get().(*Context)
    	c.writermem.reset(w)
    	c.Request = req
    	c.reset()
    
    	engine.handleHTTPRequest(c)
    
    	engine.pool.Put(c)
    }
    
    // 具体 实现 http 请求消费
    func (engine *Engine) handleHTTPRequest(c *Context) {
    	httpMethod := c.Request.Method
    	rPath := c.Request.URL.Path
    	unescape := false
    	if engine.UseRawPath && len(c.Request.URL.RawPath) > 0 {
    		rPath = c.Request.URL.RawPath
    		unescape = engine.UnescapePathValues
    	}
    
    	if engine.RemoveExtraSlash {
    		rPath = cleanPath(rPath)
    	}
    
    	// Find root of the tree for the given HTTP method
    	t := engine.trees
    	for i, tl := 0, len(t); i < tl; i++ {
    		if t[i].method != httpMethod {
    			continue
    		}
    		root := t[i].root
    		// Find route in tree
    		value := root.getValue(rPath, c.params, unescape)
    		if value.params != nil {
    			c.Params = *value.params
    		}
    		if value.handlers != nil {
    			c.handlers = value.handlers
                c.fullPath = value.fullPath
                
                // 使用 Next 实现 handler
    			c.Next()
    			c.writermem.WriteHeaderNow()
    			return
    		}
    		if httpMethod != "CONNECT" && rPath != "/" {
    			if value.tsr && engine.RedirectTrailingSlash {
    				redirectTrailingSlash(c)
    				return
    			}
    			if engine.RedirectFixedPath && redirectFixedPath(c, root, engine.RedirectFixedPath) {
    				return
    			}
    		}
    		break
    	}
    
    	if engine.HandleMethodNotAllowed {
    		for _, tree := range engine.trees {
    			if tree.method == httpMethod {
    				continue
    			}
    			if value := tree.root.getValue(rPath, nil, unescape); value.handlers != nil {
    				c.handlers = engine.allNoMethod
    				serveError(c, http.StatusMethodNotAllowed, default405Body)
    				return
    			}
    		}
    	}
        c.handlers = engine.allNoRoute
        // 未找到错误
    	serveError(c, http.StatusNotFound, default404Body)
    }
    
    //路由加入路由树
    func (group *RouterGroup) handle(httpMethod, relativePath string, handlers HandlersChain) IRoutes {
    	absolutePath := group.calculateAbsolutePath(relativePath)
    	handlers = group.combineHandlers(handlers)
    	group.engine.addRoute(httpMethod, absolutePath, handlers)
    	return group.returnObj()
    }
    
  • 相关阅读:
    codechef May Challenge 2016 CHSC: Che and ig Soccer dfs处理
    codechef May Challenge 2016 FORESTGA: Forest Gathering 二分
    codechef May Challenge 2016 LADDU: Ladd 模拟
    tp5 whereOr
    Null
    验证消息是否来自微信
    layer使用注意事项
    laravel 查询
    laravel form表单提交
    ajax上传文件
  • 原文地址:https://www.cnblogs.com/SLchuck/p/13902820.html
Copyright © 2011-2022 走看看