The standard solution to this problem is a so called "interface smuggling".
You can implement more advanced interface types of the initial interface does not provide the required abstraction, and then do type switch at runtime and gradually switch your code to use the newer interface.
Doesn't that frequently run into other code that well-intentionedly wraps a value of the original interface adding new functionality but not passing through the newer interface, because it simply can't account for all interface smuggling that might be going on? Does sophisticated Go code just not use decorator types like I've run into?
You can implement more advanced interface types of the initial interface does not provide the required abstraction, and then do type switch at runtime and gradually switch your code to use the newer interface.
The name of this technique is from https://utcc.utoronto.ca/~cks/space/blog/programming/GoInter...