Assume I have the following struct:
type myType struct {
Qid, Interval, RoundNumber string
}
and I have to make sure that a variable of type myType does not have an empty string value for any of the properties.
Is there a more idiomatic way than doing the following if:
if aMyType.Qid == "" || aMyType.Interval == "" || aMyType.RoundNumber == "" {
// handle error situation
}
Obviously the if works but I was wondering whether Go has a better way?
You might define a function on myType
that would make it easier to determine validity:
func (m myType) Valid() bool {
return m.Qid != "" && m.Interval != "" && m.RoundNumber != ""
}
And then:
if aMyType.Valid() {
// ...
}
I won't claim it's idiomatic, but if you want to play around with reflection... You can dynamically inspect the exported (capital first letter) fields of a struct. This example inspects all of the exported strings in the struct for non-empty. This doesn't handle nested structs.
http://play.golang.org/p/IjMW8OJKlc
type myType struct {
Number int
A, b, C string
}
This works by only checking for empty on exported string types.
func (m *myType) IsValid() bool {
v := reflect.ValueOf(*m)
for i := 0; i < v.NumField(); i++ {
sv := v.Field(i)
if sv.Kind() == reflect.String && sv.CanInterface() && sv.Interface() == "" {
return false
}
}
return true
}
func main() {
// false
fmt.Println((&myType{}).IsValid())
// true
fmt.Println((&myType{A: "abc", C: "123"}).IsValid())
}
For simple cases as you mentioned, I think the method you provided is more natural and more idiomatic in Go:
if mt.Qid == "" || mt.Interval == "" || mt.RoundNumber == "" {
// handle error situation
}
But if your struct is non-trivial and the validation rule is complicated, then it may be more idiomatic to leverage a dedicated library such as validating. See here for a slightly more complex use-case, and here for a very complicated use-case.
As a contrast, by using validating, the validation rule you mentioned can be implemented as follows:
import v "github.com/RussellLuo/validating"
errs := v.Validate(v.Schema{
v.F("qid", &mt.Qid): v.Nonzero(),
v.F("interval", &mt.Interval): v.Nonzero(),
v.F("round_number", &mt.RoundNumber): v.Nonzero(),
})