一、各种数据格式的响应
- json、结构体、XML、YAML类似于java的properties、ProtoBuf
Go
package main
import (
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/testdata/protoexample"
)
// 多种响应方式
func main() {
// 1.创建路由
// 默认使用了2个中间件Logger(), Recovery()
r := gin.Default()
// 1.json
r.GET("/someJSON", func(c *gin.Context) {
c.JSON(200, gin.H{"message": "someJSON", "status": 200})
})
// 2. 结构体响应
r.GET("/someStruct", func(c *gin.Context) {
var msg struct {
Name string
Message string
Number int
}
msg.Name = "root"
msg.Message = "message"
msg.Number = 123
c.JSON(200, msg)
})
// 3.XML
r.GET("/someXML", func(c *gin.Context) {
c.XML(200, gin.H{"message": "abc"})
})
// 4.YAML响应
r.GET("/someYAML", func(c *gin.Context) {
c.YAML(200, gin.H{"name": "zhangsan"})
})
// 5.protobuf格式,谷歌开发的高效存储读取的工具
// 数组?切片?如果自己构建一个传输格式,应该是什么格式?
r.GET("/someProtoBuf", func(c *gin.Context) {
reps := []int64{int64(1), int64(2)}
// 定义数据
label := "label"
// 传protobuf格式数据
data := &protoexample.Test{
Label: &label,
Reps: reps,
}
c.ProtoBuf(200, data)
})
r.Run(":8000")
}
2、JSON响应
-
http://localhost:8000/someJSON
{"message":"someJSON","status":200}
3、结构体响应
-
http://localhost:8000/someStruct
{"Name":"root","Message":"message","Number":123}
4、XML
-
This XML file does not appear to have any style information associated with it. The document tree is shown below.<map><message>abc</message></map>
5、YAML响应
-
http://localhost:8000/someYAML
name: snail
二、重定向
Go
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
r := gin.Default()
r.GET("/index", func(c *gin.Context) {
//状态码为 30(永久重定向)
c.Redirect(http.StatusMovedPermanently, "redirect-to-baidu")
})
// 定义一个路由,当访问这个路由时,会重定向到百度首页
r.GET("/redirect-to-baidu", func(c *gin.Context) {
// 百度首页的URL
baiduURL := "http://www.baidu.com"
// 重定向到百度首页,状态码为 302(临时重定向)
c.Redirect(http.StatusFound, baiduURL)
})
r.Run()
}
三、同步异步
-
goroutine机制可以方便地实现异步处理
-
另外,在启动新的goroutine时,不应该使用原始上下文,必须使用它的只读副本
Go
package main
import (
"github.com/gin-gonic/gin"
"log"
"time"
)
func main() {
// 1.创建路由
// 默认使用了2个中间件Logger(), Recovery()
r := gin.Default()
// 1.同步
r.GET("/long_sync", func(c *gin.Context) {
time.Sleep(3 * time.Second)
log.Println("同步执行:" + c.Request.URL.Path)
c.JSON(200, gin.H{"message": "同步执行", "status": 200})
})
// 2.异步
r.GET("/long_async", func(c *gin.Context) {
// 异步处理,需要搞一个副本
copyContext := c.Copy()
go func() {
time.Sleep(3 * time.Second)
log.Println("异步执行:" + copyContext.Request.URL.Path)
}()
// 异步处理允许服务器在处理请求时,不必等待当前请求完成就可以响应。
c.JSON(200, gin.H{"message": "异步执行", "status": 200})
})
r.Run(":8000")
}
使用 c.Next()
c.Next()
允许你继续执行中间件链中的下一个中间件,但不会结束当前的请求处理。这可以用来在中间件中执行一些异步操作,而不影响请求的继续处理。
Go
package main
import "github.com/gin-gonic/gin"
func main() {
router := gin.Default()
router.Use(func(c *gin.Context) {
// 执行一些异步操作
go func() {
// 异步任务
}()
c.Next() // 继续执行下一个中间件或处理函数
})
router.GET("/ping", func(c *gin.Context) {
c.JSON(200, gin.H{"message": "pong"})
})
router.Run()
}
使用 c.Abort()
c.Abort()
用于立即结束当前的请求处理,并可以返回一个响应给客户端。这通常用于在中间件中检测到某些条件不满足时,提前结束请求处理。
Go
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
router := gin.Default()
router.Use(func(c *gin.Context) {
if 1 > 0 { //中间件中检
c.AbortWithStatusJSON(http.StatusForbidden, gin.H{"error": "xxx无权限"})
return
}
c.Next() // 如果条件满足,继续执行
})
router.GET("/ping", func(c *gin.Context) {
c.JSON(200, gin.H{"message": "pong"})
})
router.Run()
}