Wrapper structs or error channels?


(Tristan Berger) #1

Looking for some API design advice.

I’m writing an API that streams a limited number of results, that may fail between any two results, and that that the consumer may wish to instruct to respond to failure by retrying with all progress intact.

Since channels have only one return value, I can’t just do val, err <- myChan.

I could do msg <- myChan, where msg is a struct{Val T; Err error}. I don’t like that it makes errors easier to ignore, makes property access a bit more verbose, and does some unnecessary allocation. I could avoid the second and lessen the third by flattening the Val struct into the message struct, at the cost of maybe some clarity loss.

I could have two separate channels, one for results and one for errors, but this makes makes iteration convoluted—you can’t just use range any more, you need a special “done” signal, etc. More opportunities to screw up, more noise while reading and writing. It also means you can’t write the API call inline.

I could do myChan, err := my.Api() then set err on failure, but besides a very counter-intuitive err behavior, this makes the consumer code for retrying on error convoluted—they need to get back into the loop somehow.

I’m thinking message structs are the best option, but want to know if anybody has a better idea.


(Johan Dahl) #2

I must agree with you. Message structs really is the best idea :slight_smile: