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
?
您关于当
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
。