Go语言入门到实战——12.Go语言错误处理

Go语言入门到实战——00主目录
在上一讲中我们学习了Go语言的接口相关的知识,面向对象的学习就结束了。

一.Go的错误机制

1.go语言不支持异常处理。
2.error类型实现了error接口
	type error interface{
		Error() string
	}
3.通过errors.New()来快速创建错误实例;//推荐使用这个方法
	errors.New("程序错误!!!")
package test

import (
	"errors"
	"fmt"
	"testing"
)

func getVal(arr []int, idx int) (int, error) {
	if idx >= len(arr) || idx < 0 {
		return 0, errors.New("idx more than length or negative")
	}
	return arr[idx], nil
}
func TestClient(t *testing.T) {
	arr := []int{1, 2, 3, 4}
	v, err := getVal(arr, 4)
	if err == nil {
		fmt.Println(v)
	} else {
		fmt.Println(err)
	}
}

//这段程序与上面的区别在于给出了一种常见的在实践中
//区分错误类型的写法
package test

import (
	"errors"
	"fmt"
	"testing"
)

var NegativeError = errors.New("idx negative")
var MoreError = errors.New("more than length")

func getVal(arr []int, idx int) (int, error) {
	if idx >= len(arr) {
		return 0, MoreError
	} else if idx < 0 {
		return 0, NegativeError
	}
	return arr[idx], nil
}
func TestClient(t *testing.T) {
	arr := []int{1, 2, 3, 4}
	v, err := getVal(arr, 4)
	if err == NegativeError {
		fmt.Println("负idx")
	} else if err == MoreError {
		fmt.Println("超过大小")
	} else {
		fmt.Println("正常大小", v)
	}
}

二.panic和recover

1.painc

1.painc用于不可恢复的错误
2.painc退出前会执行defer指定的内容
这里我们需要将painc和os.Exit()进行一下对比:
1.os.Exit()在退出时不会执行defer指定的函数
2.os.Exit()不输出当前栈调用信息
package test

import (
	"fmt"
	"os"
	"testing"
)

func TestPaincAndExit(t *testing.T) {
	fmt.Println("finally")
	os.Exit(-1)
}

package test

import (
	"errors"
	"fmt"
	"testing"
)

func TestPaincAndExit(t *testing.T) {
	fmt.Println("finally")
	panic(errors.New("error occurs"))
}


从上面两段程序我们可以看出,panic输出的结果显示了当前调用栈的信息,而os.Exit的结果则是比较简单的。接下来我们加入defer继续比较。

package test

import (
	"errors"
	"fmt"
	"testing"
)

func TestPaincAndExit(t *testing.T) {
	defer func(x int) {
		fmt.Println("finally", x)
	}(1)//这种写法之前我们没有用到过,不过这里使用到了可以很明显的看出其用法
	panic(errors.New("error occurs"))
	//下面结果我们可以看出使用painc,在程序退出前执行了defer
}

package test

import (
	"fmt"
	"os"
	"testing"
)

func TestPaincAndExit(t *testing.T) {
	defer func(x int) {
		fmt.Println("finally", x)
	}(1)
	os.Exit(-1)
	//使用os.Exit()没有执行defer
}


2.recover
我们都知道在java和c++里面有try…catch…这样的结构,那么在go里面也有类似的。

package test

import (
	"errors"
	"fmt"
	"testing"
)

func TestPaincAndExit(t *testing.T) {
	defer func() {
		if err := recover(); err != nil {
			fmt.Println("recover from", err)
		}
	}()
	panic(errors.New("error"))
}//从结果中我们发现了这时并没有报错


不过上面这种修复方式(只是把错误信息打印了一下)是非常危险的,这里给出两点建议:

1.上面这种只是打印一下错误的日志而简单的recover,可能会导致僵尸服务进程,就是这个
进程看起来是开着的,但是实际上啥也没干,而系统这是在进行health check(一般进行
健康检查就是看进程是否还或者),这个时候造成误判
2.解决办法就是采取用"let it crash"策略,也就是重启的方式
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值