键:“User.Status”错误:“required”标签上“Status”的字段验证失败

问题描述 投票:0回答:1
package main

import (
    "fmt"

    "github.com/go-playground/validator/v10"
)

type User struct {
    Status int16 `validate:"required,oneof=0 1 2"`
}

func main() {
    validate := validator.New()
    user := User{Status: 0}

    if err := validate.Struct(&user); err != nil {
        fmt.Println(err)
    } else {
        fmt.Println("Success")
    }
}

我以为程序会输出“成功”,结果却输出了

Key: 'User.Status' Error:Field validation for 'Status' failed on the 'required' tag

当我输入

user := User{Status: 1}
时,它可以正确输出
Success
。为什么?是不是因为
0
是默认的,验证者误认为我没有传入
Status

go validation
1个回答
0
投票

您关于当

Status
设置为
0
时验证失败的观察结果是正确的。在 Go 中,如果结构体字段是数字类型并且未显式初始化,则其类型的值将为零。对于
int16
,零值是
0
validator
包可以正常工作,强制使用
required
标签时该字段必须存在且不为零值。然而,在数字字段(尤其是整数)的上下文中对“必需”的解释可能有点微妙。

当您将

Status
设置为
0
时,验证器会看到该字段确实存在,但会将
0
视为整数的未初始化值或零值。这是一个常见的混淆来源,因为从逻辑上讲,您已经为
Status
提供了一个值,但从验证器的角度来看,值为
0
的数字字段仍然可以被视为“未设置”或相当于不提供一个值,因此未通过
required
验证规则。

但是,当您使用

1
Status
的任何非零值时,它会通过验证,因为现在该字段显然不处于零状态,表明它已被显式设置。

如果您希望允许

0
作为
Status
的有效值并仍然使用
required
验证规则,则可以使用
Status
的指针或考虑自定义验证逻辑。使用指针允许
nil
表示值的缺失,从而区分“未设置”和“设置为零”。以下是如何修改
User
结构以使用
Status
的指针:

package main

import (
    "fmt"
    "github.com/go-playground/validator/v10"
)

type User struct {
    Status *int16 `validate:"required,oneof=0 1 2"`
}

func main() {
    validate := validator.New()
    status := int16(0)
    user := User{Status: &status} // Now explicitly setting Status to 0

    if err := validate.Struct(&user); err != nil {
        fmt.Println(err)
    } else {
        fmt.Println("Success")
    }
}

此更改使得提供

Status
时变得明确,即使它是
0
,因为您现在设置的是指向
0
的指针,而不是依赖于默认整数值。这样,如果
required
显式设置为任何值(包括
Status
),则
0
标记将通过,因为该字段显然不是
nil

© www.soinside.com 2019 - 2024. All rights reserved.