3

I'm trying to create a method that will return the length of a generic type. If we have a string, we call len(string), or if its an array of interface{} type, we call len() on that as well. This works well, however, it doesnt work in you pass in a pointer to a string (I'm assuming I'd have the same problem with arrays and slices as well). So how can I check if I have a pointer, and dereference it?

func (s *Set) Len(i interface{}) int {
    if str, ok := i.(string); ok {
        return len(str)
    }
    if array, ok := i.([]interface{}); ok {
        return len(array)
    }
    if m, ok := i.(map[interface{}]interface{}); ok {
        return len(m)
    }
    return 0
}
kostix
  • 51,517
  • 14
  • 93
  • 176
Jameo
  • 4,507
  • 8
  • 40
  • 66
  • I'd say, in a method `func (s *Set) Len(...) int` the last statement should be `panic("Can't get length of the value")` because of [this](http://stackoverflow.com/a/22865084/720999). – kostix May 07 '14 at 16:39
  • Also note that your code has nothing to do with reflection--type assertions and type switches are "native" to Go programs while access to reflection is provided via the standard package aptly named `reflection`. – kostix May 07 '14 at 16:40
  • @kostix originally, I was trying to find a way to generically, check if the input was a pointer, and dereference it. But I realized that was overcomplicated for what I need – Jameo May 07 '14 at 18:00
  • Don't see why it was downvoted. One might have this question asked very legitimately in the code generation setting. – Artem Oboturov Sep 20 '18 at 07:28

1 Answers1

8

You can do the same thing as for the other types:

if str, ok := i.(*string); ok {
    return len(*str)
}

At this point you may want to use a type switch instead of the more verbose ifs:

switch x := i.(type) {
case string:
    return len(x)
case *string:
    return len(*x)
…
}
Steve M
  • 8,246
  • 2
  • 25
  • 26