Exceptions/Catch an exception thrown in a nested call: Difference between revisions

Content added Content deleted
(Add Seed7 example)
(→‎{{header|Go}}: Add a much simpler Go example.)
Line 1,039: Line 1,039:
trace("complete")
trace("complete")
}</lang>
}</lang>
{{out}}
Output:
<pre>
<pre>
main: start
main: start
Line 1,074: Line 1,074:
main.main()
main.main()
t.go:61 +0x31
t.go:61 +0x31
</pre>
A simpler example, closer to the task description:
<lang go>package main

import "fmt"

type U0 struct {
error
s string
}
type U1 int

func foo2() {
defer func() {
// We can't just "catch" U0 and ignore U1 directly but ...
if e := recover(); e != nil {
// e can be of any type, check for type U0
if x, ok := e.(*U0); ok {
// we can only execute code here,
// not return to the body of foo2
fmt.Println("Recovered U0:", x.s)
// We could cheat and call bar the second time
// from here, if it paniced again (even with U0)
// it wouldn't get recovered.
// Instead we've split foo into two calls to foo2.
} else {
// ... if we don't want to handle it we can
// pass it along.
fmt.Println("passing on:", e)
panic(e) // like a "re-throw"
}
}
}()
bar()
}

func foo() {
// Call bar twice via foo2
foo2()
foo2()
fmt.Println("not reached")
}

func bar() int {
return baz()
}

var done bool

func baz() int {
if !done {
done = true
panic(&U0{nil, "a message"})
}
panic(U1(42))
}

func main() {
foo()
fmt.Println("No panic")
}</lang>
[http://play.golang.org/p/X2pa8zE1Ce Run in Go Playground].
{{out}}
<pre>Recovered U0: a message
passing on: 42
panic: (main.U1) (0xfc140,0x2a) [recovered]
panic: (main.U1) (0xfc140,0x2a)
[... go-routine and stack trace omitted ...]
</pre>
</pre>