I'm working on a Go project that require calling an initiation function (initFunction
) in a separated goroutine (to ensure this function does not interfere with the rest of the project). initFunction
must not take more than 30 seconds, so I thought I would use context.WithTimeout. Lastly, initFunction
must be able to notify errors to the caller, so I thought of making an error channel and calling initFunction from an anonymous function, to recieve and report the error.
func RunInitGoRoutine(initFunction func(config string)error) error {
initErr := make(chan error)
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Seconds)
go func() {
<-ctx.Done() // Line 7
err := initFunction(config)
initErr <-err
}()
select {
case res := <-initErr:
return res.err
case <-ctx.Done():
err := errors.New("Deadline")
return err
}
}
I'm quite new to Go, so I'm asking for feedbacks about the above code.
- I have some doubt about Line 7. I used this to ensure the anonymous function is "included" under
ctx
and is therefore killed and freed and everything once timeout expires, but I'm not sure I have done the right thing. - Second thing is, I know I should be calling
cancel( )
somewhere, but I can't put my finger around where. - Lastly, really any feedback is welcome, being it about efficency, style, correctness or anything.
In Go the pratice is to communicate via channels. So best thing is probably to share a channel on your context so others can consume from the channel.
As you are stating you are new to Go, I wrote a whole bunch of articles on Go (Beginner level) https://marcofranssen.nl/categories/golang.
Read from old to new to get familiar with the language.
Regarding the channel specifics you should have a look at this article.
https://marcofranssen.nl/concurrency-in-go
A pratical example of a webserver listening for
ctrl+c
and then gracefully shutting down the server using channels is described in this blog post.https://marcofranssen.nl/improved-graceful-shutdown-webserver
In essence we run the server in a background routine
and then we have some code that is blocking the main routine by listening on a channel for the shutdown signal.
This is very similar to your usecase. So running your init in a background routine and then consume the channel waiting for the result of this init routine.
https://play.golang.org/p/_YGIrdNVZx6
You could also add an error field on the struct so you could do you usual way of error checking.