Creating a variable of type from interface in golang

huangapple go评论63阅读模式
英文:

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.

huangapple
  • 本文由 发表于 2016年11月1日 02:51:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/40348661.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定