flipped-aurora/gin-vue-admin · error

expect struct

Error message

expect struct

What it means

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.

Source

Thrown at server/utils/validator.go:133

//@param: st interface{}, roleMap Rules(入参实例,规则map)
//@return: err error

func Verify(st interface{}, roleMap Rules) (err error) {
	compareMap := map[string]bool{
		"lt": true,
		"le": true,
		"eq": true,
		"ne": true,
		"ge": true,
		"gt": true,
	}

	typ := reflect.TypeOf(st)
	val := reflect.ValueOf(st) // 获取reflect.Type类型

	kd := val.Kind() // 获取到st对应的类别
	if kd != reflect.Struct {
		return errors.New("expect struct")
	}
	num := val.NumField()
	// 遍历结构体的所有字段
	for i := 0; i < num; i++ {
		tagVal := typ.Field(i)
		val := val.Field(i)
		// 只递归进【匿名内嵌】结构体(如 global.GVA_MODEL / request.PageInfo):
		// 递归的唯一目的是够到内嵌提升上来的字段(如 IdVerify 的 ID、PageInfoVerify 的 Page)。
		// 具名关联字段(User/Dept/Meta 等)是独立业务对象,不属于当前结构体自身,不应被扫描——
		// 否则关联对象内嵌的 GVA_MODEL.ID 恒为 0,会让 IdVerify 误报"ID值不能为空"。
		// 需要单独校验某个具名子结构时,调用方直接 Verify(x.Sub, rule)(项目既有用法)。
		if tagVal.Anonymous && tagVal.Type.Kind() == reflect.Struct {
			if err = Verify(val.Interface(), roleMap); err != nil {
				return err
			}
		}
		if len(roleMap[tagVal.Name]) > 0 {
			for _, v := range roleMap[tagVal.Name] {

View on GitHub (pinned to 3136500ef3)

Solutions

  1. Pass the struct by value, not a pointer: utils.Verify(req, roleMap) instead of utils.Verify(&req, roleMap).
  2. Check for nil and dereference pointers before calling: if st != nil { st = reflect.ValueOf(st).Elem().Interface() }.
  3. Ensure the variable actually holds a struct value, not an interface{} wrapping a map or basic type; log reflect.TypeOf(st) to confirm.
  4. If you control the call site generically, guard with reflect.TypeOf(st).Kind() == reflect.Struct before invoking Verify.

Example fix

// before
req := &model.SysUser{}
if err := utils.Verify(req, utils.Rules{}); err != nil { ... }

// after
req := model.SysUser{}
if err := utils.Verify(req, utils.Rules{}); err != nil { ... }
Defensive patterns

Strategy: validation

Validate before calling

if st == nil || reflect.TypeOf(st).Kind() != reflect.Struct {
    return errors.New("Verify requires a struct value (not pointer/map/nil)")
}

Type guard

func isStruct(v interface{}) bool {
    if v == nil { return false }
    return reflect.TypeOf(v).Kind() == reflect.Struct
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of flipped-aurora/gin-vue-admin@3136500ef3 (2026-08-31). Data as JSON: /api/errors/966b08e57c1c3135. Report an issue: GitHub.