packagemainimport"fmt"funcfullName(firstName *string, lastName *string) {if firstName ==nil {panic("runtime error: first name cannot be nil") }if lastName ==nil {panic("runtime error: last name cannot be nil") } fmt.Printf("%s%s\n", *firstName, *lastName) fmt.Println("returned normally from fullName")}funcmain() { firstName :="Elon"fullName(&firstName, nil) fmt.Println("returned normally from main")}
这段程序中fullName发生panic时先执行被defer的函数调用,打印了deferred call in fullName。然后程序执行控制权转移给外层函数,接着执行外层函数被defer的函数调用,打印了deferred call in main。此时已到goroutine级别,因此不会再接着向外冒泡了。接着打印了panic信息以及调用栈。
panic: runtime error: last name cannot be nil
goroutine 1 [running]:
main.fullName(0xc000074f68, 0x0)
/Users/goWorkspace/src/test/main.go:10 +0x145
main.main()
/Users/goWorkspace/src/test/main.go:18 +0x4d
exit status 2
package main
import "fmt"
func fullName(firstName *string, lastName *string) {
defer fmt.Println("deferred call in fullName")
if firstName == nil {
panic("runtime error: first name cannot be nil")
}
if lastName == nil {
panic("runtime error: last name cannot be nil")
}
fmt.Printf("%s %s\n", *firstName, *lastName)
fmt.Println("returned normally from fullName")
}
func main() {
defer fmt.Println("deferred call in main")
firstName := "Elon"
fullName(&firstName, nil)
fmt.Println("returned normally from main")
}
deferred call in fullName
deferred call in main
panic: runtime error: last name cannot be nil
goroutine 1 [running]:
main.fullName(0xc000074f58, 0x0)
/Users/work/goWorkspace/src/test/main.go:11 +0x1d1
main.main()
/Users/work/goWorkspace/src/test/main.go:20 +0xa5
exit status 2
func recover() interface{}
package main
import "fmt"
func recoverName() {
if r := recover(); r != nil {
fmt.Println("recovered from ", r)
}
}
func fullName(firstName *string, lastName *string) {
defer recoverName()
if firstName == nil {
panic("runtime error: first name cannot be nil")
}
if lastName == nil {
panic("runtime error: last name cannot be nil")
}
fmt.Printf("%s %s\n", *firstName, *lastName)
fmt.Println("returned normally from fullName")
}
func main() {
defer fmt.Println("deferred call in main")
firstName := "Elon"
fullName(&firstName, nil)
fmt.Println("returned normally from main")
}
recovered from runtime error: last name cannot be nil
returned normally from main
deferred call in main
package main
import (
"fmt"
"time"
)
func recovery() {
if r := recover(); r != nil {
fmt.Println("recovered:", r)
}
}
func a() {
defer recovery()
fmt.Println("Inside A")
go b()
time.Sleep(1 * time.Second)
}
func b() {
fmt.Println("Inside B")
panic("oh! B panicked")
}
func main() {
a()
fmt.Println("normally returned from main")
}
Inside A
Inside B
panic: oh! B panicked
goroutine 5 [running]:
main.b()
/Users/work/goWorkspace/src/test/main.go:23 +0x79
created by main.a
/Users/work/goWorkspace/src/test/main.go:17 +0x95
exit status 2
Inside A
Inside B
recovered: oh! B panicked
normally returned from main
type Error interface {
error
// RuntimeError is a no-op function but
// serves to distinguish types that are run time
// errors from ordinary errors: a type is a
// run time error if it has a RuntimeError method.
RuntimeError()
}
package main
import "fmt"
func a() {
n := []int{5, 7, 4}
fmt.Println(n[3])
fmt.Println("normally returned from a")
}
func main() {
a()
fmt.Println("normally returned from main")
}
panic: runtime error: index out of range
goroutine 1 [running]:
main.a()
/Users/work/goWorkspace/src/test/main.go:7 +0x11
main.main()
/Users/work/goWorkspace/src/test/main.go:11 +0x22
exit status 2
package main
import "fmt"
func r() {
if r := recover(); r != nil {
fmt.Println("Recovered", r)
}
}
func a() {
defer r()
n := []int{5, 7, 4}
fmt.Println(n[3])
fmt.Println("normally returned from a")
}
func main() {
a()
fmt.Println("normally returned from main")
}
Recovered runtime error: index out of range
normally returned from main
package main
import (
"fmt"
"runtime/debug"
)
func r() {
if r := recover(); r != nil {
fmt.Println("Recovered", r)
debug.PrintStack()
}
}
func a() {
defer r()
n := []int{5, 7, 4}
fmt.Println(n[3])
fmt.Println("normally returned from a")
}
func main() {
a()
fmt.Println("normally returned from main")
}
Recovered runtime error: index out of range
goroutine 1 [running]:
runtime/debug.Stack(0xc00007a008, 0xc00006ee08, 0x2)
/usr/local/go/src/runtime/debug/stack.go:24 +0xa7
runtime/debug.PrintStack()
/usr/local/go/src/runtime/debug/stack.go:16 +0x22
main.r()
/Users/work/goWorkspace/src/test/main.go:11 +0x9c
panic(0x10a9bc0, 0x115d560)
/usr/local/go/src/runtime/panic.go:513 +0x1b9
main.a()
/Users/work/goWorkspace/src/test/main.go:18 +0x3e
main.main()
/Users/work/goWorkspace/src/test/main.go:23 +0x22
normally returned from main