英文:
Creating a variable of type from interface in golang
问题
我正在尝试使用gin框架在Go中创建验证器/绑定器中间件。
这是模型:
type LoginForm struct{
Email string `json:"email" form:"email" binding:"email,required"`
Password string `json:"password" form:"password" binding:"required"`
}
路由器:
router.POST("/login", middlewares.Validator(LoginForm{}), controllers.Login)
中间件:
func Validator(v interface{}) gin.HandlerFunc{
return func(c *gin.Context){
a := reflect.New(reflect.TypeOf(v))
err := c.Bind(&a)
if err != nil{
respondWithError(401, "Login Error", c)
return
}
c.Set("LoginForm", a)
c.Next()
}
}
我对Go语言非常陌生。我理解问题出在绑定到错误的变量上。是否有其他解决方法?
英文:
I am trying to create validator/binder middleware in go using gin framework.
This is the model
type LoginForm struct{
Email string `json:"email" form:"email" binding:"email,required"`
Password string `json:"password" form:"password" binding:"required"`
}
Router
router.POST("/login",middlewares.Validator(LoginForm{}) ,controllers.Login)
Middleware
func Validator(v interface{}) gin.HandlerFunc{
return func(c *gin.Context){
a := reflect.New(reflect.TypeOf(v))
err:=c.Bind(&a)
if(err!=nil){
respondWithError(401, "Login Error", c)
return
}
c.Set("LoginForm",a)
c.Next()
}
}
I am very new to golang. I understand the problem is with the binding to the wrong variable.
Is there any other way of solving this?
答案1
得分: 0
澄清我的评论,
在中间件中,不要使用签名func Validator(v interface{}) gin.HandlerFunc
,而是使用func Validator(f ViewFactory) gin.HandlerFunc
。
其中ViewFactory
是一个函数类型,例如type ViewFactory func() interface{}
。
中间件可以改为:
type ViewFactory func() interface{}
func Validator(f ViewFactory) gin.HandlerFunc {
return func(c *gin.Context) {
a := f()
err := c.Bind(a) // 我认为你不需要在这里传递引用,请自行检查
if err != nil {
respondWithError(401, "登录错误", c)
return
}
c.Set("LoginForm", a)
c.Next()
}
}
你可以这样编写路由器:
type LoginForm struct {
Email string `json:"email" form:"email" binding:"email,required"`
Password string `json:"password" form:"password" binding:"required"`
}
func NewLoginForm() interface{} {
return &LoginForm{}
}
router.POST("/login", middlewares.Validator(NewLoginForm), controllers.Login)
进一步地,我认为你可能需要在以后了解一下,一旦你有一个interface{}
值,你可以将其转换回LoginForm
,像这样v := some.(*LoginForm)
。
或者为了更安全,可以这样写:
if v, ok := some.(*LoginForm); ok {
// v 是一个 *LoginForm
}
有关更详细的信息,请参阅Golang类型断言。
英文:
Clarify my comment,
Instead of having the signature func Validator(v interface{}) gin.HandlerFunc
for the MW, use func Validator(f Viewfactory) gin.HandlerFunc
Where ViewFactory
if a function type such as type ViewFactory func() interface{}
the MW can be changed so
type ViewFactory func() interface{}
func Validator(f ViewFactory) gin.HandlerFunc{
return func(c *gin.Context){
a := f()
err:=c.Bind(a) // I don t think you need to send by ref here, to check by yourself
if(err!=nil){
respondWithError(401, "Login Error", c)
return
}
c.Set("LoginForm",a)
c.Next()
}
}
You can write the router like this
type LoginForm struct{
Email string `json:"email" form:"email" binding:"email,required"`
Password string `json:"password" form:"password" binding:"required"`
}
func NewLoginForm() interface{} {
return &LoginForm{}
}
router.POST("/login",middlewares.Validator(NewLoginForm) ,controllers.Login)
Going further, i think you may have to find out about this later, once you have an interface{}
value, you can make it back a LoginForm
like this v := some.(*LoginForm)
.
Or like this for more security
if v, ok := some.(*LoginForm); ok {
// v is a *LoginForm
}
See golang type assertions for more in depth information.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论