func IsValidGoValue(value interface{}, typ typs.QLInputType) bool { v := reflect.ValueOf(value) if typ, ok := typ.(*typs.QLNonNull); ok { if value == nil || v.IsNil() { return false } nullableType := typ.OfType.(typs.QLInputType) return IsValidGoValue(value, nullableType) } if value == nil || v.IsNil() { return true } v = reflect.Indirect(v) switch typ := typ.(type) { case *typs.QLList: itemType := typ.OfType.(typs.QLInputType) if v.Kind() == reflect.Slice || v.Kind() == reflect.Array { for i, n := 0, v.Len(); i < n; i++ { item := v.Index(i) if !IsValidGoValue(item, itemType) { return false } } } return IsValidGoValue(value, itemType) case *typs.QLInputObject: if v.Kind() != reflect.Struct { return false } t := v.Type() fieldsMap := typ.GetFields() for i, n := 0, t.NumField(); i < n; i++ { field := t.Field(i) fieldValue := v.Field(i) fieldType := fieldsMap[field.Name] if fieldType == nil || !IsValidGoValue(fieldValue, fieldType.Type) { return false } } return true case *typs.QLScalar: return !IsNil(typ.ParseValue(value)) case *typs.QLEnum: return !IsNil(typ.ParseValue(value)) default: panic("unreachable") } }