【问题标题】:Creating a variable of type from interface in golang从golang中的接口创建类型变量
【发布时间】:2016-10-31 18:51:15
【问题描述】:

我正在尝试使用 gin 框架创建验证器/绑定器中间件。

这是模型

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()
    }
}

我对 golang 很陌生。我知道问题在于绑定到错误的变量。 有没有其他方法可以解决这个问题?

【问题讨论】:

  • 传入工厂而不是模型变量。 type ViewFactory func() interface{}
  • 对不起,我没听懂。能否请您解释更多或提供阅读链接?

标签: go middleware go-gin


【解决方案1】:

澄清我的评论,

不要为 MW 使用签名 func Validator(v interface{}) gin.HandlerFunc,而是使用 func Validator(f Viewfactory) gin.HandlerFunc

如果是 type ViewFactory func() interface{} 等函数类型,则为 ViewFactory

MW 可以改变所以

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()
    }
}

你可以这样写路由器

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 is a *LoginForm
}

查看 golang 类型断言以获得更深入的信息。

【讨论】:

  • 这非常有效。不过,我发现了另一种方法,将 a := reflect.New(reflect.TypeOf(v)) err:=c.Bind(&a) 更改为 a := reflect.New(reflect.TypeOf(v)).Interface() err:=c.Bind(a)
  • 恐怕这仅适用于您之前介绍的简单案例。我强烈怀疑如果遇到切片、映射、通道或结构指针,事情会变得更加复杂。
猜你喜欢
  • 2022-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多