特点
- 确保调用在函数结束时发生
- 内部是一个栈,后进先出,例如
-
defer fmt.Println(1) defer fmt.Println(2) // 会输出2 1
- 遇到了return、panic依然可以输出,这里的意思是说,如果defer后边有return或panic,依然会在函数的最后执行defer后边的内容,比如
func tryDefer() { defer fmt.Println(1) defer fmt.Println(2) fmt.Println(3) return fmt.Println(4) }
这里的话输出是3 2 1,在函数最后依然会调用defer的内容,当然,如果是这样
func tryDefer() { return //请注意这个return defer fmt.Println(1) defer fmt.Println(2) fmt.Println(3) fmt.Println(4) }
那么是不会输出的,因为根本没有执行到defer语句,这和java的finally效果是不一样的
- 参数在defer语句时计算,并不是到最后输出的时候再去进行计算
关于go的出错处理
Golang没有Java的异常处理机制,Golang的错误都要自己使用err来处理,示例
文件结构:
// handler.go
func HandlerFileList(writer http.ResponseWriter, request *http.Request) error {
path := request.URL.Path[len("/list/"):]
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
all, err := ioutil.ReadAll(file)
if err != nil {
return err
}
writer.Write(all)
return nil
}
// web.go
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 {
code := http.StatusOK
switch {
case os.IsNotExist(err):
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.HandlerFileList))
http.ListenAndServe(":8888", nil)
}