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.

Reply via email to