Google资深工程师深度讲解Go语言-错误处理和资源管理(七)「建议收藏」

Google资深工程师深度讲解Go语言-错误处理和资源管理(七)

大家好,又见面了,我是全栈君。

一.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,如数组越界
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/111710.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • android vlc 中文字幕,解决Android版vlc中文乱码问题

    android vlc 中文字幕,解决Android版vlc中文乱码问题FQ到googleplaystore安装了vlc以后播放视频中文显示方框,开始以为编码问题,将字幕文件转换成utf-8以后问题依旧。android版vlc有个开发者模式,可以查看运行日志:07-0216:13:30.658D/VLC(19362):freetypesputext:Using/system/fonts/DroidSans-Bold.ttfasfont…

  • sqlserver2016安装步骤产品密钥_kepserver使用教程

    sqlserver2016安装步骤产品密钥_kepserver使用教程1.进入安装中心:可以参考硬件和软件要求、可以看到一些说明文档2.选择全新安装模式继续安装3.输入产品秘钥:这里使用演示秘钥进行4.在协议中,点击同意,并点击下一步按钮,继续安装5.进入全局规

  • GBDT算法梳理_gbdt分类

    GBDT算法梳理_gbdt分类集成算法大致分为两类:Boosting(迭代)和Bagging(装袋)。在前面的博客中,有提到,存在强依赖关系、必须串行生成的序列化方法,代表算法是Boosting,不存在强依赖关系、可同时生成的并行化方法,代表算法有Bagging、RandomForest。其中Boosting集成算法的典型代表算法有Adaboost,GBDT(GradientBoostingDecisionTree),…

    2022年10月12日
  • Flake8_quakemaker

    Flake8_quakemakerFlake8简介转载自:http://www.malike.net.cn/blog/2013/10/23/flake8-tutorial/| COMMENTSFlake8包装了下列工具:PyFlakes:静态检查Python代码逻辑错误的工具。pep8:静态检查PEP8编码风格的工具。NedBatchelder’sMcCabescript:静态

  • Nginx流媒体服务器搭建「建议收藏」

    Nginx流媒体服务器搭建「建议收藏」1.基础包下载1.1基础清单版本系统版本:CentOS7.6Nginx版本:1.20.1nginx-vod-module版本:1.29Nginx安装方面可以看我的另一篇文章Nginx笔记注意各个组件版本,可能会产生一些版本冲突1.2nginx-vod-module下载nginx点播模块,支持自动切片等功能,详细可直接去项目Gitwgethttps://github.com/kaltura/nginx-vod-module/archive/refs/tags/1.28.tar.

    2022年10月23日
  • Tar命令之增量备份

    Tar命令之增量备份

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号