代码问题
type ImageUpdateView struct {
ID uint `json:"id" binding:"required" msg:"请选择文件id"`
Name string `json:"name" binding:"required" msg:"请输入文件名称"`
}
var cr ImageUpdateView
err := c.ShouldBindJSON(&cr)
// GetValidMsg 返回结构体中的msg参数
func GetValidMsg(err error, obj any) string {
//使用时,需要传obj的指针
typeOf := reflect.TypeOf(obj)
if errs, ok := err.(validator.ValidationErrors); ok {
for _, e := range errs {
//循环每一段错误信息
//根据报错字段名.获取结构体的具体字段
if fieldByName, exits := typeOf.Elem().FieldByName(e.Field()); exits {
msg := fieldByName.Tag.Get("msg")
return msg
}
}
}
return err.Error()
}
在 Go 中,断言(Assertion)通常指的是类型断言(Type Assertion),用于在运行时判断一个接口类型的值是否具有某种特定的类型
value, ok := interfaceValue.(T)
interfaceValue
: 需要断言的接口类型值。T
: 你想要将接口值断言成的目标类型。value
: 如果断言成功,value
将是T
类型的值。ok
: 布尔值,表示断言是否成功。成功时,ok
为true
,否则为false
举例
package main
import "fmt"
type Cat struct {
Name string
}
type Dog struct {
Name string
}
type Animal interface {
Speak() string
}
func (c Cat) Speak() string {
return "Meow"
}
func (d Dog) Speak() string {
return "Woof"
}
func main() {
var animal Animal
animal = Cat{Name: "Tom"}
// 使用类型断言来判断并访问具体类型
if cat, ok := animal.(Cat); ok {
fmt.Println("它是猫:", cat.Name) // 输出: 它是猫: Tom
} else {
fmt.Println("它不是猫")
}
// 断言为 Dog 类型失败
if dog, ok := animal.(Dog); ok {
fmt.Println("它是狗:", dog.Name)
} else {
fmt.Println("它不是狗") // 输出: 它不是狗
}
}
接口使用的地方
// 使用时,需要传 obj 的指针
typeOf := reflect.TypeOf(obj)
reflect.TypeOf(obj)
: 获取obj
的类型信息(reflect.Type
类型),用于后续操作。- 为什么需要传指针?
- 如果传入的是结构体值,
reflect.TypeOf(obj)
返回的类型信息无法获取到结构体字段的tag
,因为tag
存在于类型本身,而不是值中。- 如果传入的是指针,使用
typeOf.Elem()
可以获取指针指向的结构体类型,从而访问字段信息。
if errs, ok := err.(validator.ValidationErrors); ok {
err.(validator.ValidationErrors)
: 类型断言,将err
转换为validator.ValidationErrors
类型。
validator.ValidationErrors
是validator
库中用于表示验证错误的类型,通常包含多个字段验证的错误信息。if ... ok
: 检查类型断言是否成功,只有当err
是ValidationErrors
类型时才会执行后续代码。
for _, e := range errs {
for _, e := range errs
: 遍历所有验证错误,每个错误存储在变量e
中。errs
: 这是一个切片(或数组),每个元素都代表一个字段验证失败的信息。
// 循环每一段错误信息
// 根据报错字段名,获取结构体的具体字段
if fieldByName, exits := typeOf.Elem().FieldByName(e.Field()); exits {
typeOf.Elem()
: 如果typeOf
是指针类型,Elem()
获取它指向的实际类型(即结构体类型)。FieldByName(e.Field())
: 使用验证错误中的字段名(e.Field()
),获取结构体中对应的字段信息(reflect.StructField
类型)。
e.Field()
返回验证错误中涉及的字段名。exits
: 布尔值,表示字段是否存在。
- 如果字段名在结构体中找不到,
FieldByName
返回零值,exits
为false
。
msg := fieldByName.Tag.Get("msg")
fieldByName.Tag
: 获取结构体字段的标签(reflect.StructTag
类型)。Tag.Get("msg")
: 从标签中提取msg
的值。