func frobber(s []SomeInterface) ...
However, you end up having a []ConcreteType
where ConcreteType implements SomeInterface. However, you cannot simply pass a []ConcreteType to frobber because the memory representation is different and you have to construct a new slice with the interface type, etc.Also, I don't think left-pad is an example of extreme DRY (though it should be part of a standard library). It's not an example of extreme DRY, because I think a substantial amount of programmers wil implement it incorrectly. As long as many Java-wielding friends still believe that a single char can represent any unicode code point, I have no reason to believe that the average monolingual English-speaking Go programmer will realize that you can't simply do something like:
padLen := targetLen - len(str)
(BTW, Go's fmt package provides padding.)Suppose I'm storing Tiles in a Level: the Level struct will contain a (private) RedBlackTree and I'll define GetTile(Pos) Tile and PutTile(Pos, Tile) on Level which do the casting to and from interface{}.
I still have type safety since I cannot put/get anything but Tiles in the RedBlackTree. But I didn't need generics.
Of course, in some cases you can do casting on your interface boundaries. But in many other cases this is not possible, e.g. if you want the API to return an ordered set or map.
There was definitely a lesson to be learned there, but it wasn't the one you're implying.
The aggressive code reuse in the node ecosystem is, and remains, the quality of it I respect the most.