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 +}