练习5.19: 使用panic和recover编写一个不包含return语句但能返回一个非零值的函数。
搜到以下答案,对照着进行了一些思考。
package main
import "fmt"
func main() {
a := noReturn()
fmt.Println(a)
}
func noReturn() (result int) {
defer func() {
p := recover()
result = p.(int)
}()
panic(42)
}
首先观察一下下面代码:
func main() {
s := deferDemo3()
fmt.Printf("%T %q", s, s) // string "set in defer"
}
func deferDemo3() (s string) {
defer func() {
s = "set in defer" // 可以在defer调用中对返回值进行修改
}()
return "on return"
}
从输出结果可以看到,我们可以在defer调用中对命名返回值进行修改。因此,再观察下面代码:
func main() {
s := causePanic()
fmt.Printf("%T %q", s, s) // string ""
}
func causePanic() string {
defer func() {
if p := recover(); p != nil {
fmt.Printf("recover from panic: %s\n", p)
}
}()
panic("oops!")
return "after panic" // 永远不会执行到
}
输出结果为:
recover from panic: oops!
string ""
虽然函数causePanic
的return语句因为panic导致永远无法达到,但是由于函数定义了返回值,且自动被初始化为字符串零值,所以main
函数中变量s
依然获得了返回值""
。
因此,如果返回值是命名返回值(返回值有名字),则可以在panic终止了函数causePanic
继续运行后,同样可以在defer调用中对返回值进行修改,前提是必须是返回值必须有名字。
func main() {
s := causePanic()
fmt.Printf("%T %q", s, s) // string "set in defer"
}
func causePanic() (s string) {
defer func() {
if p := recover(); p != nil {
fmt.Printf("recover from panic: %s\n", p)
s = "set in defer" // 在defer中对返回值s进行修改
}
}()
panic("oops!")
return "after panic" // 永远不会执行到
}
输出结果为:
recover from panic: oops!
string "set in defer"
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。