Reputation: 4354
I've been trying to find something that answers this question but I can't find anything that talks about it.
Lets say I have a function in Go which is something like this:
func main() {
// assume this wrapped in a waitgroup or something
// so that it doesnt exit
go queue.ConsumeAndDoSomething()
go api.StartServer()
}
I have two goroutines here that do completely different things and one should ideally keep running if the other crashes/panics. If the queue operation fails, the API server should be impacted and vice versa.
I'm not sure if this possible (or even recommended). Is there a clean way of doing this or should the whole program exit once a goroutine panics?
Upvotes: 4
Views: 5521
Reputation: 1614
Each goroutine must defer a recover
call to recover from a potential panic if you want other goroutine to not be impacted.
Instead of
go queue.ConsumeAndDoSomething()
You should use
go func(){
defer func() {
if r := recover(); r != nil {
log.Error("goroutine paniqued: ", r)
}
}()
queue.ConsumeAndDoSomething()
}()
Upvotes: 2
Reputation: 418505
You have to use the builtin recover()
function to recover from panics, and you have to call it in a deferred function.
Let's say you have a function that may panic:
func doPanic() {
log.Println("about to panic")
panic("test")
}
Create a helper function to launch a function as a goroutine "protected" (from panics):
func protect(f func()) {
defer func() {
if err := recover(); err != nil {
log.Printf("Recovered: %v", err)
}
}()
f()
}
And use it like this:
func main() {
go protect(doPanic)
for {
time.Sleep(time.Second)
fmt.Println("tick")
}
}
This test app will output:
2021/03/04 14:12:31 about to panic
2021/03/04 14:12:31 Recovered: test
tick
tick
tick
...
See related question: Generic panic recovering in go programs
Upvotes: 7