{"record":{"id":"966b08e57c1c3135","repo":"flipped-aurora/gin-vue-admin","slug":"expect-struct","errorCode":null,"errorMessage":"expect struct","messagePattern":"expect struct","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/utils/validator.go","lineNumber":133,"sourceCode":"//@param: st interface{}, roleMap Rules(入参实例，规则map)\n//@return: err error\n\nfunc Verify(st interface{}, roleMap Rules) (err error) {\n\tcompareMap := map[string]bool{\n\t\t\"lt\": true,\n\t\t\"le\": true,\n\t\t\"eq\": true,\n\t\t\"ne\": true,\n\t\t\"ge\": true,\n\t\t\"gt\": true,\n\t}\n\n\ttyp := reflect.TypeOf(st)\n\tval := reflect.ValueOf(st) // 获取reflect.Type类型\n\n\tkd := val.Kind() // 获取到st对应的类别\n\tif kd != reflect.Struct {\n\t\treturn errors.New(\"expect struct\")\n\t}\n\tnum := val.NumField()\n\t// 遍历结构体的所有字段\n\tfor i := 0; i < num; i++ {\n\t\ttagVal := typ.Field(i)\n\t\tval := val.Field(i)\n\t\t// 只递归进【匿名内嵌】结构体(如 global.GVA_MODEL / request.PageInfo):\n\t\t// 递归的唯一目的是够到内嵌提升上来的字段(如 IdVerify 的 ID、PageInfoVerify 的 Page)。\n\t\t// 具名关联字段(User/Dept/Meta 等)是独立业务对象,不属于当前结构体自身,不应被扫描——\n\t\t// 否则关联对象内嵌的 GVA_MODEL.ID 恒为 0,会让 IdVerify 误报\"ID值不能为空\"。\n\t\t// 需要单独校验某个具名子结构时,调用方直接 Verify(x.Sub, rule)(项目既有用法)。\n\t\tif tagVal.Anonymous && tagVal.Type.Kind() == reflect.Struct {\n\t\t\tif err = Verify(val.Interface(), roleMap); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t\tif len(roleMap[tagVal.Name]) > 0 {\n\t\t\tfor _, v := range roleMap[tagVal.Name] {","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/flipped-aurora/gin-vue-admin/blob/3136500ef380842b0eb6c4daa87c3f8a47fcf9e0/server/utils/validator.go#L115-L151","documentation":"Verify in server/utils/validator.go is a reflection-based struct validator that reads custom `mj:` tags from each struct field. It first reflects the input with reflect.TypeOf/reflect.ValueOf and requires the dynamic kind to be reflect.Struct. If a caller passes a non-struct (nil, pointer-to-something, map, slice, or basic type), Verify returns errors.New(\"expect struct\") instead of validating. The library throws this to prevent reflect panics like NumField on a non-struct kind.","triggerScenarios":"Calling utils.Verify(st, roleMap) where st is nil, a pointer (e.g. &req), a map[string]interface{}, a slice, or a primitive such as a string or int. Note that in Go, reflect.ValueOf(&req{}).Kind() is reflect.Ptr, so even a pointer to a struct triggers this error.","commonSituations":"Developers pass a request-binding pointer (form.ShouldBindJSON returns *Struct) straight into Verify, pass an uninitialized interface{} variable, or call Verify in a generic helper where the argument type is interface{} and nothing guarantees a struct value was stored.","solutions":["Pass the struct by value, not a pointer: utils.Verify(req, roleMap) instead of utils.Verify(&req, roleMap).","Check for nil and dereference pointers before calling: if st != nil { st = reflect.ValueOf(st).Elem().Interface() }.","Ensure the variable actually holds a struct value, not an interface{} wrapping a map or basic type; log reflect.TypeOf(st) to confirm.","If you control the call site generically, guard with reflect.TypeOf(st).Kind() == reflect.Struct before invoking Verify."],"exampleFix":"// before\nreq := &model.SysUser{}\nif err := utils.Verify(req, utils.Rules{}); err != nil { ... }\n\n// after\nreq := model.SysUser{}\nif err := utils.Verify(req, utils.Rules{}); err != nil { ... }","handlingStrategy":"validation","validationCode":"if st == nil || reflect.TypeOf(st).Kind() != reflect.Struct {\n    return errors.New(\"Verify requires a struct value (not pointer/map/nil)\")\n}","typeGuard":"func isStruct(v interface{}) bool {\n    if v == nil { return false }\n    return reflect.TypeOf(v).Kind() == reflect.Struct\n}","tryCatchPattern":null,"preventionTips":["Always pass struct values, never pointers, to utils.Verify","In generic helpers, assert reflect kind Struct before calling Verify","Add a unit test exercising Verify with the real request struct"],"tags":["go","reflection","validation","gin-vue-admin"],"backgroundTag":"validator-non-struct-input","analyzedSha":"3136500ef380842b0eb6c4daa87c3f8a47fcf9e0","analyzedAt":"2026-08-31T13:50:02.721Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}