func<T> id(t T) T {
switch t := T.(type) {
case int: return t + 1;
default: return t;
}
}
The ability to examine on types at runtime can enable some interesting programs, but it also means that you don't get guarantees like you do in languages like Haskell. An example of this biting someone in practice is this blog post[1], where the author reasoned that because a library function expected an io.Reader, all it would do is use the Read method as exposed by Reader. In reality, though, the function was able to branch on the type and determine whether it also exposed a Close method, and called that if it could. That kind of feature destroys the useful static guarantees provided by parametric polymorphism in other languages like ML or Haskell.[1]: http://how-bazaar.blogspot.co.nz/2013/07/stunned-by-go.html