go error 和panic的兜底处理(1)

go中的重要的点:
  • go中是以package为单位进行引用文件 , 一个文件夹下面只有一个package,所以通过引用src下面的文件路径,就可以引用这个package下面的所有的公共的 ==数据结构 ==
  • go中所有的数据结构(type) 都可以进行实现接口
  • go中所有的 == 数据结构== 都可以作为变量进行传递

建立简单的具有err和panic处理的web接口

  • 手法一 : 对核心的函数进行扩展(对err和panic)的处理 and 适配

  • panic的放入和recover的取出错误

  • controller 核心处理请求的逻辑,返回不同的错误


// todo 处理函数只管处理 ,如果有错误就把错误返回,  将错误交给其他人进行处理

const prefix = "/list/"
func Handler (writer http.ResponseWriter, request *http.Request) error{



	//todo 查看是否包含这个匹配头
	if strings.Index(request.URL.Path,prefix) != 0 {
		return userError("Path must start "+ "with "+prefix)
	}


	path := request.URL.Path[len(prefix):] //todo 取出请求的匹配部分
	file, err := os.Open(path)
	if err != nil{
		return err
	}
	defer file.Close()
	bytes, err := ioutil.ReadAll(file)
	if err != nil {
		return err
	}
	writer.Write(bytes)
	return nil
}



type userError string

func (u userError) Error() string {
	return u.Message()
}

func (u userError) Message() string {
	return string(u)
}

  • 对核心处理函数的扩展包装 适配


//todo 设置一种函数变量类型
type AppHandler func(http.ResponseWriter, *http.Request) error



//todo 在一种函数类型中进行拓展 修改为另一种函数结构返回; 也算是适配器的功能;
func ErrHandler(app_handler AppHandler) func(http.ResponseWriter, *http.Request){
	return func(writer http.ResponseWriter, request *http.Request){

		//todo 对panic的兜底处理
		defer func() {
			r := recover()  //todo 从recover中调出错误,兜底对错误进行处理;
			if r==nil{
				return
			}

			if err, ok := r.(error); ok {
				log.Printf("Error handle request : %s ",err.Error())
				http.Error(writer,http.StatusText(http.StatusInternalServerError),http.StatusInternalServerError)
			}else{
				panic(r)
			}
		}()

		//todo 真正的处理函数的运行
		err := app_handler(writer,request)

		//todo 自定义的函数的错误处理 ---> 1 usererrinfo handle(根据类型判定是否为user错误)    2 systeminfo handle
		if err != nil {
			log.Printf("Error handle request : %s ",err.Error())


			//todo 面向用户的一些错误的拦截,输出
			if userErr,ok :=err.(UserErr); ok {
				http.Error(writer,userErr.Message(),http.StatusBadRequest)
				return
			}


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

	}
}

type UserErr interface{
	error  //在一个接口中包含的另一个接口 todo 是给系统看的
	Message() string  //todo 单独的有关用户信息输出的错误 给用户看的
}


  • 函数运行
func main() {
	http.HandleFunc("/", ErrHandler(fileHandle.Handler))
	err := http.ListenAndServe(":8866", nil)
	if err != nil {
		panic(err)
	}
}

go自带代码test

两个部分
  • 测试case的成功率,覆盖率
  • 测试代码的性能 速度
  • 可以查看代码每部分的耗能情况
规范以及实际实现
  • 规范
func  TestTriangle(t *testing.T){
	Test := []struct {
		a,b,c int32
	}{
		{1,2,3},
		{0,2,2},
		{0,0,0},
		{-1,1,0},
		{math.MaxInt32,1,math.MinInt32},
	}

	for _, _ = range Test {
		_ =LengthOfLongestSubs("sfdfdsfddsfdsfdsfdfsdfdftring")
	}
}

go test . 测试case的通过情况
结果 : ok awesomeProject/learnGo/tableTest 0.005s

  • 测试运行的性能 快慢
func BenchmarkSubstr (b *testing.B){

	for i:=0;i<b.N ;i++{

		_ =LengthOfLongestSubs("sfdfdsfddsfdsfdsfdfsdfdftring")


	}
}

go test -bench .

  • result :
goos: darwin
goarch: amd64
pkg: awesomeProject/learnGo/tableTest
BenchmarkSubstr-4        2188663               553 ns/op
PASS
ok      awesomeProject/learnGo/tableTest        1.770s

代码细节耗能查看
  • 查看代码每一部分的耗能情况 go test -bench . -cpuprofile cpu.out 生成一个二进制文件
  • go tool pprof cpu.out 进入一个交互式的命令行 —> web
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值