I'm curious on what kind of patterns should used in Go for such cases. So let's suppose, you have a Request
struct that holds some information for making an HTTP request, along with the parameters that can be sent in the payload and their respective validations. Now different type of validations would be applicable on the basis of the data type of the parameter, so I decided to use a map[string]Validations
, where I could store the type of Validations mentioned in the Validations
union (basically, being able to accomodate both IntValidations
& StrValidations
in the same map).
But the below code would result in an error because Validations
can only be used as a type parameter, so how can we achieve this in Go? In Java this could be easily achieved with polymorphism, where Validation
would be the parent class and int and float validations would be the child classes, so later on we could easily instantiate a HashMap
of Validations
.
Note: I would want to avoid the usage of map[string]interface{}
.
type Validations interface {
IntValidations | StrValidations
}
type IntValidations struct {
MaxVal int
MinVal int
}
type StrValidations struct {
MinLength int
MaxLength int
Regex string
}
type Request struct {
Path string
Payload map[string]Validations // Error: Validations cannot be used outside of a type constraint.
}
As pointed out by @Cerise Limón in the comments, you can do it like so
package main
type Validators interface {
Validate(value any) error // Can return bool also
}
type IntValidator struct {
MaxVal int
MinVal int
}
func (intValidator *IntValidator) Validate(value any) error {
// run validations
return nil
}
type StrValidator struct {
MinLength int
MaxLength int
Regex string
}
func (strValidator *StrValidator) Validate(value any) error {
// run validations
return nil
}
type Request struct {
Path string
Payload map[string]Validations
}
Now you can add validators with
func main() {
request := Request{Payload: make(map[string]Validations)}
request.Payload["myIntVar"] = &IntValidations{MinVal: 10, MaxVal: 20}
request.Payload["myStrVar"] = &IntValidations{MinLen: 10, MaxLen: 15, Regex: "[a-z]+"}
if err := request.Payload["myIntVar"].Validate(13); err != nil {
panic("could not validate")
}
}