From 4cb65ecbac8da344467f15ae51868d187d55fcdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8B=AC=E5=AD=A4=E4=BC=B6=E4=BF=9C?= <1184662350@qq.com> Date: Mon, 12 Dec 2022 01:12:00 +0800 Subject: [PATCH] =?UTF-8?q?day7=E5=87=BD=E6=95=B0=20Panic=E6=9C=BA?= =?UTF-8?q?=E5=88=B6=20recover=E6=9C=BA=E5=88=B6=20=E7=BB=83=E4=B9=A05.19?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/study/day7Function/Panic.go | 31 ++++++++++++++ .../day7Function/Practice/Practice5.19.go | 27 ++++++++++++ src/study/day7Function/Recover.go | 42 +++++++++++++++++++ 3 files changed, 100 insertions(+) create mode 100644 src/study/day7Function/Panic.go create mode 100644 src/study/day7Function/Practice/Practice5.19.go create mode 100644 src/study/day7Function/Recover.go diff --git a/src/study/day7Function/Panic.go b/src/study/day7Function/Panic.go new file mode 100644 index 0000000..45808b1 --- /dev/null +++ b/src/study/day7Function/Panic.go @@ -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) +} diff --git a/src/study/day7Function/Practice/Practice5.19.go b/src/study/day7Function/Practice/Practice5.19.go new file mode 100644 index 0000000..76aea75 --- /dev/null +++ b/src/study/day7Function/Practice/Practice5.19.go @@ -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) +} diff --git a/src/study/day7Function/Recover.go b/src/study/day7Function/Recover.go new file mode 100644 index 0000000..7f9791a --- /dev/null +++ b/src/study/day7Function/Recover.go @@ -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 +}