Reputation: 1
It is about defer and recover, to catch runtime error.
version 1:
func a() {
defer func() {
if r := recover(); r != nil {
fmt.Println(r)
}
}()
b()
}
func b() {
go fmt.Println([]string{}[2])
}
func main() {
a()
time.Sleep(1 * time.Second)
fmt.Println("end")
}
Version 2 (Only func b() changed) :
func b() {
go func() {
fmt.Println([]string{}[2])
}()
}
difference run version 1:
> go run /tmp/version1.go
runtime error: index out of range
end
and version 2:
> go run /tmp/t.go
panic: runtime error: index out of range
goroutine 5 [running]:
main.b.func1()
/tmp/t.go:19 +0x109
created by main.b
/tmp/t.go:20 +0x2b
goroutine 1 [sleep]:
time.Sleep(0x3b9aca00)
/usr/local/go/src/runtime/time.go:59 +0xf9
main.main()
/tmp/t.go:25 +0x29
exit status 2
why it looks different? thank you if someone can give me the detail message.
Upvotes: 0
Views: 436
Reputation: 11626
In version 1, your panic happens in the main goroutine because []string{}[2] must be resolved before the goroutine can be spawned.
All arguments to a function must be resolved before it gets dispatched, and goroutines are no different.
A goroutine works basically the same as any other function call except that after the stack is setup for the call, it executes in a separate context (thread).
in your second example, you are calling a function with no args and then in that function you are panicing. Since there is no call to recover() in the goroutine, you are seeing the default panic handler.
defer/recover() can only capture a panic within the same goroutine.
If you add a defer / recover to the top of b, you will be able to capture it and do whatever (ie: println it like you did in #1)
Upvotes: 4