Unknown Types in Go are the Worst

Say you have some data and it’s either an int or a string (of an int).

thing1 := thing{num: 2}
thing2 := thing{num: "31"}

Well, that sucks.

Go is a typed language and this bit of data really should be properly an int. But, ya know, the world is a mess sometimes. Perhaps you have a giant database of JSON data put in there over a decade and this num value is sometimes a proper int and sometimes a string-of-an-int. We might have to json.Unmarshal that data, and the only way we’ll be able to do that safely is a forgiving type. Poop happens.

Assuming we can’t up and fix the data in the database right this second, we have to code around it. So our thing type needs to be forgiving:

type thing struct {
  num interface{}
}

YEAH FINE.

But this problem is going to keeping spreading its ugly tentacles. There is a good chance that num really wants to be an int and when it interacts with other code, the expectation that it is an int will be enforced.

Maybe we just have the world’s simplest little function that prints the int it accepts:

func printNumber(i int) {
  fmt.Println(i)
}

Can we use it with our data?

printNumber(thing1.num)
printNumber(thing2.num)

Absolutely not. We don’t have an int, we have an interface{}. In JavaScript, we could toss whatever through parseInt() and it will come out as an integer. No such loosey-goosey action in Go.

  • There is an int() function, but it’ll choke on the string.
  • Likewise, thing1.num.(int) will choke on the string.

So, we’ll need to look at the value, check the type, and then really explicitly perform a conversion based on the type we find.

func intFromInterface(v interface{}) (int, error) {
  switch v := v.(type) {
  case int:
    return int(v), nil
  case string:
    c, err := strconv.Atoi(v)
    if err != nil {
      return 0, err
    }
    return c, nil
  default:
    return 0, fmt.Errorf("conversion to int from %T not supported", v)
  }
}

You might want to add more types to that if your data has more potential types. Floats and whatnot.

That’s a big messy function if you ask me, but it’s better to get the data converted into the type it should be in as early as possible, rather than passing it around as an interface{} and passing the buck on converting the type to other places.

Here’s a playground link of all that.


One response to “Unknown Types in Go are the Worst”

  1. Saurabh sharma says:

    This problem could be solved only if golang had geenrics but I think they have so things will get better.

Leave a Reply

Your email address will not be published.