gin中間request body繫結到不同的結構體中
阿新 • • 發佈:2021-10-27
1.一般通過呼叫c.Request.Body
方法繫結資料,但不能多次呼叫這個方法。
package main import ( "fmt" "github.com/gin-gonic/gin" ) type FormA struct { Foo string `form:"foo" json:"foo" binding:"required"` } type FormB struct { Bar string `json:"bar" binding:"required"` } func someHandler(c *gin.Context) { // 一般通過c.request.body繫結資料,但是不能多次呼叫這個方法 objA := FormA{} objB := FormB{} // c.ShouldBind 使用了 c.Request.Body 不可重用 // 注意:ShouldBind方法,如果是GET請求,前臺必須使用form-data傳參 if err := c.ShouldBind(&objA); err == nil { fmt.Println(objA.Foo) c.String(200, "the body should be FormA") // 因為現在 c.Request.Body 是EOF,所以這裡會報錯 } else if err := c.ShouldBind(&objB); err == nil { c.String(200, "the body should be FormB") } else { fmt.Println(err) fmt.Println("未執行") } } func main() { router := gin.Default() router.POST("/ping", someHandler) router.Run() }
2.要想多次繫結,可以使用c.ShouldBindBodyWith
.
package main
import (
"fmt"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
)
type FormA struct {
Foo string `form:"foo" json:"foo" binding:"required"`
}
type FormB struct {
Bar string `json:"bar" binding:"required"`
}
func someHandler(c *gin.Context) {
objA := FormA{}
objB := FormB{}
// 讀取 c.Request.Body 並將結果存入上下文。
if err := c.ShouldBindBodyWith(&objA, binding.JSON); err == nil {
fmt.Println(objA.Foo)
c.String(200, "the body should be FormA")
// 這時, 複用儲存在上下文中的 body。
} else if err := c.ShouldBindBodyWith(&objB, binding.JSON); err == nil {
c.String(200, "the body should be FormB")
} else {
fmt.Println(err)
fmt.Println("未執行")
}
}
func main() {
router := gin.Default()
router.POST("/ping", someHandler)
router.Run()
}
c.ShouldBindBodyWith
會在繫結之前將 body 儲存到上下文中。 這會對效能造成輕微影響,如果呼叫一次就能完成繫結的話,那就不要用這個方法。- 只有某些格式需要此功能,如
JSON
,XML
,MsgPack
,ProtoBuf
。 對於其他格式, 如Query
,Form
,FormPost
,FormMultipart
可以多次呼叫c.ShouldBind()
而不會造成任任何效能損失。