day7函数 Panic机制 recover机制 练习5.19
parent
010c5bc593
commit
4cb65ecbac
|
@ -0,0 +1,31 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
// 当发生 panic时,会立即执行该GorouTime的defer函数,
|
||||||
|
// 然后程序崩溃, 并输出日志信息
|
||||||
|
// 日志信息包括panic的文字描述, 函数名, 报错行号, 堆栈信息
|
||||||
|
|
||||||
|
// 勤奋的程序员认为任何崩溃都表明代码中存在漏洞,
|
||||||
|
// 所以对于大部分漏洞,我们应该使用Go提供的错误机制,
|
||||||
|
// 而不是panic,尽量避免程序的崩溃。
|
||||||
|
|
||||||
|
defer printStack()
|
||||||
|
f(3)
|
||||||
|
}
|
||||||
|
func printStack() {
|
||||||
|
var buf [4096]byte
|
||||||
|
n := runtime.Stack(buf[:], false)
|
||||||
|
os.Stdout.Write(buf[:n])
|
||||||
|
}
|
||||||
|
func f(x int) {
|
||||||
|
fmt.Printf("f(%d)\n", x+0/x) // panics if x == 0
|
||||||
|
defer fmt.Printf("defer %d\n", x)
|
||||||
|
f(x - 1)
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
ret := practice()
|
||||||
|
fmt.Println(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func practice() (result int) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
log.Println("Recovered in f", r)
|
||||||
|
// 断言, 参考第七章7.10节的内容
|
||||||
|
// see: https://zhuanlan.zhihu.com/p/149015320
|
||||||
|
// 具体作用为检查接口中是否包含int类型的值, 并返回该值
|
||||||
|
// panic接受一个类型为any的参数
|
||||||
|
// 该参数的any类型实际为一个空接口
|
||||||
|
// 参考Go安装目录 /src/builtin/builtin.go:95 :252
|
||||||
|
result = r.(int) // 断言 int
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
panic(34)
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"Study/src/study/day7Function/HtmlTools"
|
||||||
|
"fmt"
|
||||||
|
"golang.org/x/net/html"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// 定义该defer语句的函数发生了panic异常,recover会使程序从panic中恢复,
|
||||||
|
t, _ := soleTitle(HtmlTools.GetHtml())
|
||||||
|
fmt.Println(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// soleTitle returns the text of the first non-empty title element
|
||||||
|
// in doc, and an error if there was not exactly one.
|
||||||
|
func soleTitle(doc *html.Node) (title string, err error) {
|
||||||
|
type bailout struct{}
|
||||||
|
defer func() {
|
||||||
|
switch p := recover(); p {
|
||||||
|
case nil: // no panic
|
||||||
|
case bailout{}: // "expected" panic
|
||||||
|
err = fmt.Errorf("multiple title elements")
|
||||||
|
default:
|
||||||
|
panic(p) // unexpected panic; carry on panicking
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
// Bail out of recursion if we find more than one nonempty title.
|
||||||
|
HtmlTools.ForEachNode(doc, func(n *html.Node) {
|
||||||
|
if n.Type == html.ElementNode && n.Data == "title" &&
|
||||||
|
n.FirstChild != nil {
|
||||||
|
if title != "" {
|
||||||
|
panic(bailout{}) // multiple titleelements
|
||||||
|
}
|
||||||
|
title = n.FirstChild.Data
|
||||||
|
}
|
||||||
|
}, nil)
|
||||||
|
if title == "" {
|
||||||
|
return "", fmt.Errorf("no title element")
|
||||||
|
}
|
||||||
|
return title, nil
|
||||||
|
}
|
Loading…
Reference in New Issue