Как получить динамический тип пустого интерфейса

#validation #go #go-gin

# #валидация #Вперед #гоу-джин

Вопрос:

Я попытался протестировать проверку данных запроса в фреймворке go-gin, пока не добрался до этого кода, который работает нормально.

 // RegisterEmailPasswordValidator it is used for validation and json marshalling
type RegisterEmailPasswordValidator struct {
    Email    string `json:"email" binding:"required,email"`
    Password string `json:"password" binding:"required,gte=6,lte=30"`
}

// Validate used in views
func (v *RegisterEmailPasswordValidator) Validate( c *gin.Context) error {
    if err := c.ShouldBindJSON(v); err != nil {
        return err
    }
    return nil
}

// use it like this in my controller
var validator validations.RegisterEmailPasswordValidator
err := validator.Validate(c)
 

Чтобы быть СУХИМ, я попытался добавить глобальную функцию для проверки ответственности за все структуры. Я попытался добавить функцию с пустым интерфейсом, как показано ниже.

 // Validate used in views
func Validate(c *gin.Context, customValidator interface{}) error {   
    if err := c.ShouldBindJSON(amp;customValidator); err != nil {
        return err
    }
    return nil
}

// use it like this in my controller
var validator validations.RegisterEmailPasswordValidator
err := validations.Validate(c, amp;validator)
 

Но это не работает, когда я отправляю CustomValidator в ShouldBindJSON, он использует пустой интерфейс, а не динамический тип.

Есть ли какой-нибудь способ использовать динамический тип CustomValidator без указания его типа? Я попытался отразить.
Есть ли лучший способ быть СУХИМ в этой ситуации в go?

Комментарии:

1. @ILoveReflection Я попробовал ваше предложение, есть ошибка json: Unmarshal(проверки без указателей. RegisterEmailPassword)

2. Я неправильно понял код. Я не вижу, где используется функция проверки. Игнорируйте мой предыдущий комментарий.

3. Вы не должны отправлять указатель на интерфейс своей функции. Также я предполагаю, что ввод в ShouldBindJson — это интерфейс, и он у вас уже есть, зачем передавать указатель на этот интерфейс?

4. @Mastisa Принятый ответ — это именно то, что я предложил. Тем не менее, код в вопросе не использует функцию проверки, поэтому я все еще в замешательстве.

5. Я точно не помню ваше предложение, но в вашем предложении была ошибка, о которой я упоминал.

Ответ №1:

Вы должны передавать интерфейс как есть, а не указатель на интерфейс. что-то вроде этого :

 // Validate used in views
func Validate(c *gin.Context, customValidator interface{}) error {   
    if err := c.ShouldBindJSON(customValidator); err != nil {
        return err
    }
    return nil
}

// use it like this in my controller
var validator validations.RegisterEmailPasswordValidator
err := validations.Validate(c, amp;validator)
 

Причина в том, что указатели в Go — это не то же самое, что указатели в C / C , они сохраняют ссылку на тип и значение. Указатель на интерфейс не является указателем на тип, который он содержит, но это указатель на сам интерфейс, тип — это интерфейс. В ShouldBindJSON функции пытается получить объект путем отражения, но он получает тип интерфейса и ссылку, а не validator ссылку s, поэтому он не может выполнить свою работу, поскольку ему нужен тип, а не интерфейс.

Комментарии:

1. Указатели в Go такие же, как и указатели в C / C . Это разные значения интерфейса.