1. 22
    1. 4

      But then it would be difficult to know how to pipe the result into the next function, unless we change Doer’s type to be:

      type Doer func(context.Context, interface{}) interface{}
      

      I think what you’d want is type Doer interface{}, and treat a Doer as a function. You can then call it using reflection. Your Impl could do this work and ensure the output types of the previous doer match the input types of the next doer.

      This of course makes the API a bit more obscure, but it can be done. This was actually the subject of a blog post I wrote right around the time Go 1.1 was released: https://blog.burntsushi.net/type-parametric-functions-golang/

      Also, it kind of seems like this should be called resultdoer or eitherdoer, since “maybe” to me implies that there’s no error information (just that a procedure failed).

    2. 7

      But why do this, instead of using a language that is intended for the desired level of abstraction?

      It’s not like even if this worked less painfully that Go people would accept it as “good”/“idiomatic” code.

      (Likely that many Go users wouldn’t understand the code, given they have self-selected into that kind of language that avoids it.)

      1. 1

        I can’t use Rust at work :(

        1. 9

          I recommend sticking with a style that your coworkers feel comfortable with. Turning Go into Rust or any other language should be done with a great deal of consideration for your peers.