I don't think there is such support in Go generics as of now. I may be wrong though.
The alternative is to use reflection. Here is the simplified code of your example: ```go func GetValidator(field Field) Validator { return Validator{ Validate: func() (int, error) { value := reflect.ValueOf(field.Value) if value.Kind() != reflect.Map && value.Kind() != reflect.Slice && value.Kind() != reflect.Array { return 0, errors.New("invalid type") } return value.Len(), nil }, } } ``` On Friday, March 18, 2022 at 5:47:29 PM UTC+7 RussellLuo wrote: > Thanks for your reply, Henry! > > I admit that my problem seems a little bit silly without providing > the contextual information. Actually I am trying to rewrite my little > [validation library](https://github.com/RussellLuo/validating) by > leveraging Go generics. > > For the originally non-generic [Len]( > https://pkg.go.dev/github.com/RussellLuo/validating/v2#Len) validator > factory, I have implemented two generic versions. One for a slice: > > ```go > // LenSlice is a leaf validator factory used to create a validator, which > will > // succeed when the length of the slice field is between min and max. > func LenSlice[T ~[]E, E any](min, max int) (mv *MessageValidator) { > mv = &MessageValidator{ > Message: "with an invalid length", > Validator: Func(func(field *Field) Errors { > v, ok := field.Value.(T) > if !ok { > return NewUnsupportedErrors(field, > "LenSlice") > } > > l := len(v) > if l < min && l > max { > return NewErrors(field.Name, ErrInvalid, > mv.Message) > } > return nil > }), > } > return > } > ``` > > and the other for a map: > > ```go > // LenMap is a leaf validator factory used to create a validator, which > will > // succeed when the length of the map field is between min and max. > func LenMap[T map[K]V, K comparable, V any](min, max int) (mv > *MessageValidator) { > mv = &MessageValidator{ > Message: "with an invalid length", > Validator: Func(func(field *Field) Errors { > v, ok := field.Value.(T) > if !ok { > return NewUnsupportedErrors(field, > "LenMap") > } > > l := len(v) > if l < min && l > max { > return NewErrors(field.Name, ErrInvalid, > mv.Message) > } > return nil > }), > } > return > } > ``` > > As a result, we can use them as below: > > ```go > Schema{ > F("slice", []string{"foo"}): LenSlice[[]string](0, 2), > F("map", map[string]int{"a": 1, "b": 2}): > LenMap[map[string]int](0, 2), > } > ``` > > *Now I am wondering if I can merge the above two versions into one generic > `Len`, with the help of a constraint, say, SliceOrMap*. For example: > > ```go > func Len[T SliceOrMap](min, max int) (mv *MessageValidator) { > mv = &MessageValidator{ > Message: "with an invalid length", > Validator: Func(func(field *Field) Errors { > v, ok := field.Value.(T) > if !ok { > return NewUnsupportedErrors(field, "Len") > } > > l := len(v) > if l < min && l > max { > return NewErrors(field.Name, ErrInvalid, > mv.Message) > } > return nil > }), > } > return > } > ``` > > Then we can use the same `Len` for both a slice and a map as below instead: > > ```go > Schema{ > F("slice", []string{"foo"}): Len[[]string](0, 2), > F("map", map[string]int{"a": 1, "b": 2}): Len[map[string]int](0, > 2), > } > ``` > > *(NOTE*: I have posted this reply earlier, but is was not displayed > (maybe due to my wrong choice of "Reply to author"). Now I post it again > by selecting "Reply all".) > On Friday, March 18, 2022 at 3:07:17 PM UTC+8 Henry wrote: > >> Have you considered this? >> ```go >> func IsBetween(value, min, max int) bool { >> return value>=min && value <=max >> } >> >> if IsBetween(len(myMap), 10, 25) { >> //do something >> } >> ``` >> >> On Friday, March 18, 2022 at 11:20:37 AM UTC+7 RussellLuo wrote: >> >>> Hi there, >>> >>> Thanks to Go generics in 1.18, I can write a generic function >>> `LenBetween` for a slice: >>> >>> ```go >>> func SliceLenBetween[T ~[]E, E any](s T, min, max int) bool { >>> return len(s) >= min && len(s) <= max >>> } >>> ``` >>> >>> as well as for a map: >>> >>> ```go >>> func MapLenBetween[T map[K]V, K comparable, V any](s T, min, max int) >>> bool { >>> return len(s) >= min && len(s) <= max >>> } >>> ``` >>> >>> Is there any way to write a constraint, say, SliceOrMap, to support >>> either a slice or a map? >>> >>> With the help of SliceOrMap, then I can write a more generic version >>> `LenBetween` like this: >>> >>> ```go >>> func MapLenBetween[T SliceOrMap](s T, min, max int) bool { >>> return len(s) >= min && len(s) <= max >>> } >>> ``` >>> >>> Thanks in advance! >>> >> -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/3ee74f75-9c07-4334-a149-25594560cacbn%40googlegroups.com.