Great post, thank you! Found you Wrap method looks exactly like my decorate :).
While not entirely satisfying it does solve the problem and the set of optional methods in my case is always below 5 so the effort is manageable. Since the optional interfaces are really narrow (always 1 method) I guess I can proceed with this approach... Kind regards, Andi On Wednesday, August 26, 2020 at 5:59:13 PM UTC+2 axel.wa...@googlemail.com wrote: > Hi, > > no, there isn't really a solution to this. I've blogged about this: > > https://blog.merovius.de/2017/07/30/the-trouble-with-optional-interfaces.html > A combination of generics and embedding can help. So, you can do > > type Wrapper[T] struct { > T > otherFields > } > > func (w *Wrapper) SomeNewMethod() { > } > > But even then, you need to know the static type of what you're wrapping > (so http Middleware, for example, couldn't use this). > > I'm also not super sure if it's a good idea to do this even if you could. > An interface might contain multiple, interdependent methods. As an example, > `http.ResponseWriter` implicitly calls `WriteHeader` the first time you > call `Write`. So, if you wrap a `ResponseWriter` and overwrite > `WriteHeader`, that overwritten method has to be called explicitly (the > underlying `ResponseWriter` will call its own `WriteHeader`). So if you > don't know what the methods of the wrapped type are and do, you might > introduce very hard to find bugs. > > On Wed, Aug 26, 2020 at 5:49 PM cpu...@gmail.com <cpu...@gmail.com> wrote: > >> Hi All, >> >> using interfaces for behavioural testing seems a common pattern in go: >> >> if typed, hasCapability := d.(Capability); hasCapability... >> >> I have the requirement to dynamically compose interfaces at runtime, i.e. >> I cannot know upfront which set of interfaces a resulting type will support: >> >> type resultingType interface { >> basicCapability >> ...any combination of additional capabilities >> } >> >> If there is only a single additional/optional capability to implement >> that is simple to solve, e.g. by implementing a wrapping struct that embeds >> the basic capability and adds an additional capability. Applying this >> pattern across multiple layers (stack of wrapping structs does not work as >> the embedded interfaces don't bubble up). >> >> However, the number of additional capabilities that a type might have to >> support could be bigger (think of physical meters which could supply power, >> energy, currents, frequency etc). >> >> I'm solved this by using go:generate which is fed the basic and set of >> optional types and generates additional types for any _combination_ of >> additional types, an example is attached (and source at >> https://github.com/andig/evcc/pull/310/files#diff-fa40c05651b4682eb25a198f8a4a98f0). >> >> This is similar to the "old" pattern of simulation generics via generated >> code. >> >> I'm wondering if using a pattern of dynamic composition is sound, if the >> the go:generate approach is a good one or if there are better ways? >> >> Kind regards, >> Andi >> >> -- >> You received this message because you are subscribed to the Google Groups >> "golang-nuts" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to golang-nuts...@googlegroups.com. >> To view this discussion on the web visit >> https://groups.google.com/d/msgid/golang-nuts/217cee40-1e00-442d-a4d2-7d4a37e41544n%40googlegroups.com >> >> <https://groups.google.com/d/msgid/golang-nuts/217cee40-1e00-442d-a4d2-7d4a37e41544n%40googlegroups.com?utm_medium=email&utm_source=footer> >> . >> > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/bacb1b26-daf2-49b3-8d56-e9530803e6f4n%40googlegroups.com.