I'm looking for a function that would reduce the redundancy in accessing a member of a struct pointer in Go. It should perform the member access if the pointer is not nil
, or return a default value otherwise. It should be functionally equivalent to:
var ptr *MyStruct
var result any
if ptr != nil {
result = ptr.MyField
} else {
result = sql.NullFloat64{}
}
In principle, this pattern comes from the orElse
of optionals in many other languages. The use case is to extract a field from a nested protobuf message and stuff it into a SQL query. The resulting function looks like the following:
func GetFieldOrElse(v any, fn string, or any) any {
segments := strings.Split(fn, ".")
r := reflect.ValueOf(v)
for _, field := range segments {
if r.IsNil() {
return or
}
r = reflect.Indirect(r).FieldByName(field)
}
return r.Interface()
}
// pi is a protobuf message and ExtraParams is a nested message inside `pi`
GetFieldOrElse(pi.ExtraParams, "Make", sql.NullString{})
GetFieldOrElse(pi.ExtraParams, "Model", sql.NullString{})
GetFieldOrElse(pi.ExtraParams, "LensModel", sql.NullString{})
GetFieldOrElse(pi.ExtraParams, "Aperture.Numerator", sql.NullInt64{})
GetFieldOrElse(pi.ExtraParams, "Aperture.Denominator", sql.NullInt64{})
I tried to look for a compile-time solution (i.e. without reflection) but failed. Is this the idiomatic way of achieving this goal?
Aucun commentaire:
Enregistrer un commentaire