Golang Gin(中)

摘要:
快速入门使用GET、POST、PUT、PATCH、DELETE和OPTIONS funmain(){//Createsaginrouterwithdefaultmiddleware://loggerandrecovery(无故障)middlewarerouter:=gin.Default()router.GET(“/someGet”,GET)router.POST(

快速入门

Using GET, POST, PUT, PATCH, DELETE and OPTIONS

func main() {
    // Creates a gin router with default middleware:
    // logger and recovery (crash-free) middleware
    router := gin.Default()

    router.GET("/someGet", getting)
    router.POST("/somePost", posting)
    router.PUT("/somePut", putting)
    router.DELETE("/someDelete", deleting)
    router.PATCH("/somePatch", patching)
    router.HEAD("/someHead", head)
    router.OPTIONS("/someOptions", options)

    // By default it serves on :8080 unless a
    // PORT environment variable was defined.
    router.Run()
    // router.Run(":3000") for a hard coded port
}

Parameters in path

func main() {
    router := gin.Default()

    // This handler will match /user/john but will not match /user/ or /user
    router.GET("/user/:name", func(c *gin.Context) {
        name := c.Param("name")
        c.String(http.StatusOK, "Hello %s", name)
    })

    // However, this one will match /user/john/ and also /user/john/send
    // If no other routers match /user/john, it will redirect to /user/john/
    router.GET("/user/:name/*action", func(c *gin.Context) {
        name := c.Param("name")
        action := c.Param("action")
        message := name + " is " + action
        c.String(http.StatusOK, message)
    })

    // For each matched request Context will hold the route definition
    router.POST("/user/:name/*action", func(c *gin.Context) {
        c.FullPath() == "/user/:name/*action" // true
    })

    router.Run(":8080")
}

Querystring parameters

func main() {
    router := gin.Default()

    // Query string parameters are parsed using the existing underlying request object.
    // The request responds to a url matching:  /welcome?firstname=Jane&lastname=Doe
    router.GET("/welcome", func(c *gin.Context) {
        firstname := c.DefaultQuery("firstname", "Guest")
        lastname := c.Query("lastname") // shortcut for c.Request.URL.Query().Get("lastname")

        c.String(http.StatusOK, "Hello %s %s", firstname, lastname)
    })
    router.Run(":8080")
}

Multipart/Urlencoded Form

func main() {
    router := gin.Default()

    router.POST("/form_post", func(c *gin.Context) {
        message := c.PostForm("message")
        nick := c.DefaultPostForm("nick", "anonymous")

        c.JSON(200, gin.H{
            "status":  "posted",
            "message": message,
            "nick":    nick,
        })
    })
    router.Run(":8080")
}

Another example: query + post form

POST /post?id=1234&page=1 HTTP/1.1
Content-Type: application/x-www-form-urlencoded

name=manu&message=this_is_great
func main() {
    router := gin.Default()

    router.POST("/post", func(c *gin.Context) {

        id := c.Query("id")
        page := c.DefaultQuery("page", "0")
        name := c.PostForm("name")
        message := c.PostForm("message")

        fmt.Printf("id: %s; page: %s; name: %s; message: %s", id, page, name, message)
    })
    router.Run(":8080")
}
id: 1234; page: 1; name: manu; message: this_is_great

Map as querystring or postform parameters

POST /post?ids[a]=1234&ids[b]=hello HTTP/1.1
Content-Type: application/x-www-form-urlencoded

names[first]=thinkerou&names[second]=tianou
func main() {
    router := gin.Default()

    router.POST("/post", func(c *gin.Context) {

        ids := c.QueryMap("ids")
        names := c.PostFormMap("names")

        fmt.Printf("ids: %v; names: %v", ids, names)
    })
    router.Run(":8080")
}
ids: map[b:hello a:1234]; names: map[second:tianou first:thinkerou]

Upload files

Single file

The filename is always optional and must not be used blindly by the application: path information should be stripped, and conversion to the server file system rules should be done.

func main() {
    router := gin.Default()
    // Set a lower memory limit for multipart forms (default is 32 MiB)
    router.MaxMultipartMemory = 8 << 20  // 8 MiB
    router.POST("/upload", func(c *gin.Context) {
        // single file
        file, _ := c.FormFile("file")
        log.Println(file.Filename)

        // Upload the file to specific dst.
        c.SaveUploadedFile(file, dst)

        c.String(http.StatusOK, fmt.Sprintf("'%s' uploaded!", file.Filename))
    })
    router.Run(":8080")
}

How to curl:

curl -X POST http://localhost:8080/upload 
  -F "file=@/Users/appleboy/test.zip" 
  -H "Content-Type: multipart/form-data"

Multiple files

See the detail example code.

func main() {
    router := gin.Default()
    // Set a lower memory limit for multipart forms (default is 32 MiB)
    router.MaxMultipartMemory = 8 << 20  // 8 MiB
    router.POST("/upload", func(c *gin.Context) {
        // Multipart form
        form, _ := c.MultipartForm()
        files := form.File["upload[]"]

        for _, file := range files {
            log.Println(file.Filename)

            // Upload the file to specific dst.
            c.SaveUploadedFile(file, dst)
        }
        c.String(http.StatusOK, fmt.Sprintf("%d files uploaded!", len(files)))
    })
    router.Run(":8080")
}

How to curl:

curl -X POST http://localhost:8080/upload 
  -F "upload[]=@/Users/appleboy/test1.zip" 
  -F "upload[]=@/Users/appleboy/test2.zip" 
  -H "Content-Type: multipart/form-data"

Grouping routes

func main() {
    router := gin.Default()

    // Simple group: v1
    v1 := router.Group("/v1")
    {
        v1.POST("/login", loginEndpoint)
        v1.POST("/submit", submitEndpoint)
        v1.POST("/read", readEndpoint)
    }

    // Simple group: v2
    v2 := router.Group("/v2")
    {
        v2.POST("/login", loginEndpoint)
        v2.POST("/submit", submitEndpoint)
        v2.POST("/read", readEndpoint)
    }

    router.Run(":8080")
}

Blank Gin without middleware by default

Use

r := gin.New()

instead of

// Default With the Logger and Recovery middleware already attached
r := gin.Default()

Using middleware

func main() {
    // Creates a router without any middleware by default
    r := gin.New()

    // Global middleware
    // Logger middleware will write the logs to gin.DefaultWriter even if you set with GIN_MODE=release.
    // By default gin.DefaultWriter = os.Stdout
    r.Use(gin.Logger())

    // Recovery middleware recovers from any panics and writes a 500 if there was one.
    r.Use(gin.Recovery())

    // Per route middleware, you can add as many as you desire.
    r.GET("/benchmark", MyBenchLogger(), benchEndpoint)

    // Authorization group
    // authorized := r.Group("/", AuthRequired())
    // exactly the same as:
    authorized := r.Group("/")
    // per group middleware! in this case we use the custom created
    // AuthRequired() middleware just in the "authorized" group.
    authorized.Use(AuthRequired())
    {
        authorized.POST("/login", loginEndpoint)
        authorized.POST("/submit", submitEndpoint)
        authorized.POST("/read", readEndpoint)

        // nested group
        testing := authorized.Group("testing")
        testing.GET("/analytics", analyticsEndpoint)
    }

    // Listen and serve on 0.0.0.0:8080
    r.Run(":8080")
}

Custom Recovery behavior

func main() {
    // Creates a router without any middleware by default
    r := gin.New()

    // Global middleware
    // Logger middleware will write the logs to gin.DefaultWriter even if you set with GIN_MODE=release.
    // By default gin.DefaultWriter = os.Stdout
    r.Use(gin.Logger())

    // Recovery middleware recovers from any panics and writes a 500 if there was one.
    r.Use(gin.CustomRecovery(func(c *gin.Context, recovered interface{}) {
        if err, ok := recovered.(string); ok {
            c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
        }
        c.AbortWithStatus(http.StatusInternalServerError)
    }))

    r.GET("/panic", func(c *gin.Context) {
        // panic with a string -- the custom middleware could save this to a database or report it to the user
        panic("foo")
    })

    r.GET("/", func(c *gin.Context) {
        c.String(http.StatusOK, "ohai")
    })

    // Listen and serve on 0.0.0.0:8080
    r.Run(":8080")
}

How to write log file

func main() {
    // Disable Console Color, you don't need console color when writing the logs to file.
    gin.DisableConsoleColor()

    // Logging to a file.
    f, _ := os.Create("gin.log")
    gin.DefaultWriter = io.MultiWriter(f)

    // Use the following code if you need to write the logs to file and console at the same time.
    // gin.DefaultWriter = io.MultiWriter(f, os.Stdout)

    router := gin.Default()
    router.GET("/ping", func(c *gin.Context) {
        c.String(200, "pong")
    })

    router.Run(":8080")
}

Custom Log Format

func main() {
    router := gin.New()

    // LoggerWithFormatter middleware will write the logs to gin.DefaultWriter
    // By default gin.DefaultWriter = os.Stdout
    router.Use(gin.LoggerWithFormatter(func(param gin.LogFormatterParams) string {

        // your custom format
        return fmt.Sprintf("%s - [%s] "%s %s %s %d %s "%s" %s"
",
                param.ClientIP,
                param.TimeStamp.Format(time.RFC1123),
                param.Method,
                param.Path,
                param.Request.Proto,
                param.StatusCode,
                param.Latency,
                param.Request.UserAgent(),
                param.ErrorMessage,
        )
    }))
    router.Use(gin.Recovery())

    router.GET("/ping", func(c *gin.Context) {
        c.String(200, "pong")
    })

    router.Run(":8080")
}

Sample Output

::1 - [Fri, 07 Dec 2018 17:04:38 JST] "GET /ping HTTP/1.1 200 122.767µs "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.80 Safari/537.36" "

Controlling Log output coloring

By default, logs output on console should be colorized depending on the detected TTY.

Never colorize logs:

func main() {
    // Disable log's color
    gin.DisableConsoleColor()
    
    // Creates a gin router with default middleware:
    // logger and recovery (crash-free) middleware
    router := gin.Default()
    
    router.GET("/ping", func(c *gin.Context) {
        c.String(200, "pong")
    })
    
    router.Run(":8080")
}

Always colorize logs:

func main() {
    // Force log's color
    gin.ForceConsoleColor()
    
    // Creates a gin router with default middleware:
    // logger and recovery (crash-free) middleware
    router := gin.Default()
    
    router.GET("/ping", func(c *gin.Context) {
        c.String(200, "pong")
    })
    
    router.Run(":8080")
}

免责声明:文章转载自《Golang Gin(中)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇objective-c(十二)关于Foundation框架shell脚本开发环境的配置和优化实践下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

随便看看

Python3 读取和写入excel

/py_工作/销售/包括/天气。csv'_工作簿函数读取并返回所有工作表● 以列表形式读取_仅:判断是否读取_仅以模式打开Excel文档● 编码:...

nginx 反向代理

nginx反向代理Docker部署Apache服务Docker部署nginx服务修改nginx侦听和转发配置Docker部署Apache服务创建Dockerfile,编写以下内容,并执行dockerbuild-tv4/Apache创建v4/apacheimage。修改后,执行nginxsroad以重新加载服务测试请求/品种请求/caesar...

unity, 设置帧率上限

使用unity制作演示,并移除所有昂贵的特效。在真正的机器上运行仍然会导致问题。最大显示帧速率为30。默认情况下,IOS设备上统一的原始帧速率限制为30。应用targetFrameRate=60;更改为最大值60。请注意,此设置对编辑器没有影响。...

Mysql 查询以某个字符开头的语句

为了查询以某个字符开头的数据,MySQL中经常使用它。常见的语句如下:以查询文章标题以单词“positive”开头的语句为例:使用通配符:1SELECT*FROM`article`,其中title类似于“positive%”;使用左函数:使用字符串截断函数:1SELECT*FROM`article`其中substring(title,1,1)='positi...

Grafana 安装配置启动

多个数据源:Graphite、InfluxDB、OpenTSDB、Prometheus、Elasticsearch、CloudWatch、KairosDB、Zabbix等。通知和提醒,达到目标设置的阈值,并发出警报。grafana具有以下三个用户权限管理员:超级管理员,具有所有权限查看器:只能查看DashBoardEditer:无法创建用户,无法添加数据源,...

Windows 远程桌面连接ubuntu及xrdp的一些小问题(远程桌面闪退、连接失败、tab补全功能,无菜单栏,error

想要修改,在windowsmanager中,keyboard里将用到Super+Tab的快捷键clear掉即可。解决:通过设置sesman.in文件内的参数解决:cat/etc/xrdp/sesman.inivi/etc/xrdp/sesman.ini可以修改会话设置:将最大会话限制该大MaxSessions=50;将KillDisconnected=1;则...