Gin
Gin
下载:
go get -u github.com/gin-gonic/gin
导入:
import "github.com/gin-gonic/gin"
基本使用
启动服务
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
r := gin.Default()
// 定义路由
r.GET("hello", func(c *gin.Context) {
c.String(http.StatusOK, "hello")
})
// r.Run() // 默认监听8080
r.Run(":8080") // 指定监听端口
}
获取请求信息
// 获取请求对象
request := c.Request
// 获取请求方法信息
// 此方法返回string类型
method := request.Method
fmt.Println(method)
// 获取请求uri信息
// 此方法返回 *url.URL 类型,可以获取URL中的所有信息
var url *url.URL = request.URL
fmt.Println(url)
// 获取请求头信息
// 此方法返回 http.Header 类型,可获取请求头中的所有信息
header := request.Header
fmt.Println(header)
// 获取请求体信息
// 此方法返回 io.ReadCloser 类型,可以从流中读取请求体数据
body := request.Body
fmt.Println(body)
处理不同的请求方法
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)
路径参数
必选的路径参数用:
表示,name
必须存在,否则不会匹配:
router.GET("/user/:name", func(c *gin.Context) {
name := c.Param("name")
c.String(http.StatusOK, "Hello %s", name)
})
可选的路径参数用*
表示,可以匹配/user/lisi
和/user/lisi/play
:
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)
})
查询参数
router.GET("/welcome", func(c *gin.Context) {
firstname := c.DefaultQuery("firstname", "Guest")
lastname := c.Query("lastname") // 等同于 c.Request.URL.Query().Get("lastname")
c.String(http.StatusOK, "Hello %s %s", firstname, lastname)
})
Multipart/Urlencoded Form 表单处理
router.POST("/form_post", func(c *gin.Context) {
message := c.PostForm("message") // 获取表单字段,message
nick := c.DefaultPostForm("nick", "anonymous") // 获取表单字段 nick,并给予缺省值
c.JSON(200, gin.H{
"status": "posted",
"message": message,
"nick": nick,
})
})
表单/查询参数数据转换map
POST /post?ids[a]=1234&ids[b]=hello HTTP/1.1
Content-Type: application/x-www-form-urlencoded
names[first]=thinkerou&names[second]=tianou
router.POST("/post", func(c *gin.Context) {
ids := c.QueryMap("ids")
names := c.PostFormMap("names")
fmt.Printf("ids: %v; names: %v", ids, names)
// ids: map[b:hello a:1234]; names: map[second:tianou first:thinkerou]
})
文件上传
一次处理单个文件:
curl -X POST http://localhost:8080/upload \
-F "file=@/Users/appleboy/test.zip" \
-H "Content-Type: multipart/form-data"
// 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) {
// 从form中取出指定的文件字段
file, _ := c.FormFile("file")
log.Println(file.Filename)
// 将文件保存到指定路径
c.SaveUploadedFile(file, dst)
c.String(http.StatusOK, fmt.Sprintf("'%s' uploaded!", file.Filename))
})
一次处理多个文件:
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"
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)
c.SaveUploadedFile(file, dst)
}
c.String(http.StatusOK, fmt.Sprintf("%d files uploaded!", len(files)))
})
Gin的中间件
Gin默认启动的路由(gin.Default()
)自带集成两个中间件:
Logger
日志处理Recovery
错误处理
启动一个不带中间件的路由
r := gin.New()
启用某些中间件
r := gin.New()
r.Use(gin.Logger())
r.Use(gin.Recovery())
Logger全局中间件
日志写入文件:
func main() {
// 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")
}
自定义日志格式:
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\"\n",
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")
}
日志着色:
// 默认情况下,会根据选择的tty对日志进行着色
// 禁用日志着色
gin.DisableConsoleColor()
// 始终启用日志着色
gin.ForceConsoleColor()
Recovery全局中间件
路由分组
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)
}
认证分组
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")
}
最后更新于
这有帮助吗?