Google资深工程师深度讲解Go语言-错误处理和资源管理(七)
【摘要】
一.defer调用:实现资源管理
确保调用在函数结束时发生参数在defer语句时计算defer列表为后进先出
何时使用defer调用
Open/CloseLock/UnlockPrintHeader/PrintFooter
package main import "fmt" func tryDefer(){ defer fmt.Pr...
一.defer调用:实现资源管理
- 确保调用在函数结束时发生
- 参数在defer语句时计算
- defer列表为后进先出
何时使用defer调用
- Open/Close
- Lock/Unlock
- PrintHeader/PrintFooter
-
package main
-
-
import "fmt"
-
-
func tryDefer(){
-
defer fmt.Println(1)
-
defer fmt.Println(2)//defer 相当于栈:先进后出
-
fmt.Println(3)
-
//结果:3 2 1
-
}
-
func main() {
-
tryDefer()
-
}
-
package main
-
-
import (
-
"../../functional/fib"
-
"bufio"
-
"fmt"
-
"os"
-
)
-
-
func tryDefer() {
-
defer fmt.Println(1)
-
defer fmt.Println(2) //defer 相当于栈:先进后出
-
fmt.Println(3)
-
//结果:3 2 1
-
//return
-
panic("error occurred")
-
fmt.Println(4)
-
//3
-
//2
-
//1
-
//panic: error occurred
-
}
-
//参数在defer语句时计算
-
func tryDefer2() {
-
for i := 0; i < 100; i++ {
-
defer fmt.Println(i) //
-
if i == 10 {
-
panic("print too many")
-
}
-
}
-
}
-
-
func writeFile(filename string) {
-
file, err := os.Create(filename)
-
if err != nil {
-
panic(err)
-
}
-
defer file.Close()
-
-
writer := bufio.NewWriter(file)
-
defer writer.Flush()
-
-
f := fib.Fibonacci()
-
for i := 0; i < 10; i++ {
-
fmt.Fprintln(writer, f())
-
}
-
}
-
-
func main() {
-
//tryDefer()
-
tryDefer2()
-
writeFile("fib.txt")
-
}
二.错误处理理念
-
func writeFile(filename string) {
-
//file, err := os.Create(filename)
-
file, err := os.OpenFile(filename, os.O_EXCL|os.O_CREATE, 0666) //O_EXCL 如果文件存在的话打开不了
-
// panic: open fib.txt: file exists
-
err = errors.New("this is a custum error")
-
if err != nil {
-
//fmt.Println("Error:",err.Error())
-
if pathError, ok := err.(*os.PathError); !ok {
-
panic(err)
-
} else {
-
fmt.Printf("%s ,%s ,%s\n ", pathError.Op, pathError.Path, pathError.Err)
-
}
-
return
-
}
-
defer file.Close()
-
-
writer := bufio.NewWriter(file)
-
defer writer.Flush()
-
-
f := fib.Fibonacci()
-
for i := 0; i < 10; i++ {
-
fmt.Fprintln(writer, f())
-
}
-
}
三.服务器统一出错处理
web.go
-
package main
-
-
import (
-
"./filelisting"
-
"log"
-
"net/http"
-
"os"
-
)
-
-
type appHandler func(writer http.ResponseWriter, request *http.Request) error
-
-
//错误包装
-
func errWrapper(handler appHandler) func(http.ResponseWriter, *http.Request) {
-
return func(writer http.ResponseWriter, request *http.Request) {
-
err := handler(writer, request)
-
if err != nil {
-
log.Printf("Error handing request:%s",err.Error()) //2020/08/29 17:17:36 Error handing request:open fib2.txt: permission denied
-
code := http.StatusOK
-
switch {
-
case os.IsNotExist(err):
-
//http.Error(writer, http.StatusText(http.StatusNotFound), http.StatusNotFound)
-
code = http.StatusNotFound
-
case os.IsPermission(err):
-
code = http.StatusForbidden
-
default:
-
code = http.StatusInternalServerError
-
}
-
http.Error(writer, http.StatusText(code), code)
-
}
-
}
-
}
-
func main() {
-
http.HandleFunc("/list/", errWrapper(filelisting.HandleFileList))
-
-
err := http.ListenAndServe(":8081", nil)
-
if err != nil {
-
panic(err)
-
}
-
}
handler.go
-
package filelisting
-
-
import (
-
"io/ioutil"
-
"net/http"
-
"os"
-
)
-
-
func HandleFileList(writer http.ResponseWriter, request *http.Request) error {
-
path := request.URL.Path[len("/list/"):]
-
file, err := os.Open(path)
-
if err != nil {
-
//panic(err)
-
/*http.Error(writer,
-
err.Error(),
-
http.StatusInternalServerError)
-
return*/
-
return err
-
}
-
defer file.Close()
-
-
all, err := ioutil.ReadAll(file)
-
if err != nil {
-
//panic(err)
-
return err
-
}
-
writer.Write(all)
-
return nil
-
}
四.panic和recover
panin功能作用
- 停止当前函数执行
- 一直向上返回,执行每一层的defer
- 如果没有遇见recover,程序退出
recover功能作用
- 仅在defer调用中使用
- 获取panic的值
- 如果无法处理,可重新panic
-
package main
-
-
import (
-
"fmt"
-
)
-
-
func tryRecover() {
-
defer func() {
-
r := recover()
-
if err, ok := r.(error); ok {
-
fmt.Println("Error occurred:", err)
-
} else {
-
fmt.Println(r)
-
}
-
}()
-
-
//panic(errors.New("this is an error")) //Error occurred: this is an error,下面不执行,panic停止当前函数执行
-
-
b := 0
-
a := 5 / b
-
fmt.Println(a) //Error occurred: runtime error: integer divide by zero
-
}
-
func main() {
-
tryRecover()
-
}
五.服务器统一出错处理
- 意料之中的:使用error,如文件打不开
- 意料之外的:使用panic,如数组越界
文章来源: blog.csdn.net,作者:lxw1844912514,版权归原作者所有,如需转载,请联系作者。
原文链接:blog.csdn.net/lxw1844912514/article/details/108291996
【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)