I have this code in my project:
//data.Objects is a map[string]interface{}
corporateName := data.Objects["corporateName"].(string)
dba := data.Objects["dba"].(string)
licence := data.Objects["licence"].(string)
resaleCert := data.Objects["resaleCert"].(string)
einNumber := data.Objects["einNumber"].(string)
phoneNumber := data.Objects["phoneNumber"].(string)
website := data.Objects["website"].(string)
contactName := data.Objects["contactName"].(string)
email := data.Objects["email"].(string)
billingAddress := data.Objects["billingStreet"].(string)
billingCity := data.Objects["billingCity"].(string)
billingCode := data.Objects["billingCode"].(int64)
billingState := data.Objects["billingState"].(string)
billingCountry := data.Objects["billingContry"].(string)
deliveryAddress := data.Objects["deliveryAddress"].(string)
In the declared map, some of these key couldn't have a value associated so they can return nil. If they do that I'm not able to do a type conversion. I'm looking for a way in order to improve this access and prevent the incorrect conversion.
Using some if else to check it it's quite annoying and verbose. Is there a way in order to avoid it?
N.B. The nil values for the structure are perfectly legal in this case so it's not a problem that I can avoid before.
As @JimB mentions you can use a custom type, e.g.
type detailsMap map[string]interface{}
func (dm detailsMap) String(key string) string {
if val, ok := dm[key].(string); ok {
return val
}
return ""
}
func (dm detailsMap) Int64(key string) int64 {
if val, ok := dm[key].(int64); ok {
return val
}
return 0
}
Note that default zero values are returned if the desired key
is not present in the type's underlying map[string]interface{}
.
If you haven't got control of the original data.Objects
then you can convert it to a detailsMap
via detailsMap(data.Objects)
.
You can then get values out as follows:
corporateName := dm.String("corporateName")
website := dm.String("website")
billingCode := dm.Int64("billingCode")
Here's an example on the playground.
If you find the repeated if-else annoying (which you should, and I agree), create a new function to help manage it.
Write a local interfaceToString(i *interface) string
method which returns nil
if the map object is nil, and otherwise returns the object as converted to a string. You can put an if statement there, and keep that function out of the way of your code.
Then just call that function on each returned element of your map, rather than casting it directly.