While I agree that this sort of functionality is incredibly, incredibly useful-- I'm primarily a Scala dev for my day job these days and this is one of the more popular and powerful features, though they have given it the unfortunate name of "pimping"-- it is one of the major pain points, especially for new people to the language, and can get convoluted and difficult to reason about rather quickly. Scala does it with something it calls implicit conversions. Basically you define a new subtype of the object in question and add the desired functionality there, then define an implicit method to convert the existing type to your new type. So, if I defined something like a RichNode with a prettyPrint method on it and implicit conversions from all those types you listed to this new RichNode, I could just call .prettyPrint() as if it existed on the original and the compiler would use implicit resolution to do the conversion for me.
I don't see how something like this could work at all in Go's type system, though, since a type is essentially only defined by what methods it contains and there is no notion of subtyping. Perhaps you could make a NodeMangler that is a utility class, essentially a correction of functions that operate on a Node and has all the functionality you want? Then, anywhere you need to in the code, you just call any of those methods, passing along any of these different kinds of Node?
2. if the API owner evolves it, it might conflict with your own extensions)
1. you can't share code