I'm building a go library that manages and writes data to a file. I have written a file writer that I can pass data to, and it'll write that data to the file via a buffered writer. This means that a service using the library will have to call a close method once the service shuts down to write anything still in the buffer. I see two ways of handling this:
- Expose a
Close
method that the service can use. - Use channels. If the service closes the channel, that'll close the buffer in the library. My lib function would look like this:
func (r *Repo) Write(ctx context.Context, data <-chan Data, errCh chan<- error) error {
for doc := range data {
err := r.file.Write(ctx, doc)
if err != nil {
errCh <- err
}
}
err = r.file.Close(ctx)
return err
}
My question is if the Write()
signature make sense, as it takes a receive channel and a send channel for errors as input? I haven't seen similar examples of this. Maybe there is a better way of organising this?
CodePudding user response:
Option 1. i.e. using Close
function makes more sense especially if one looks at the go way of doing things.
Also using channels complicates things when things can be done without them.
Like the Write
implementation has a for loop which keeps on reading data.
for doc := range data {
err := r.file.Write(ctx, doc)
if err != nil {
errCh <- err
}
}
this means any one calling this write function would get blocked and will need to call this into a goroutine if non-blocking behaviour is required.
Additionally having a simple write signature like:
func (r *Repo) Write(data Data) error
looks more clean, and the context can be made a part of Repo
initialisation if that's not changing each time function is getting called.