go编程中容易忽略的技术点

《go in action》已经写的很好了,但是还有很多内容没有涉及到,如果我们不明确,可能会在工作中犯错误。我们离一个gopher还是有很大的差距,需要不断练习。

panic,error,recover

可类比java语言,传统的try-catch方式可以将代码块包括起来,进行代码块级的异常捕获,并且如果异常没有处理,所在线程会退出,但不会导致整个程序崩溃。看下golang中关于异常和错误的典型语句:

panic("数据库连接失败")
if r:=recover();r!=nil{
	// panic处理
}
val,err:=<-ch
if err!=nil{
	// 错误处理
}

而go呢,panic和recover看起来都是方法,可以被调用,使用起来很方便,其实要recover到异常,需要在defer函数中直接调用,例如下面HandlePanic函数,如果在HandlePanic再嵌套函数调用recover,则捕获不到。这源于底层数据结构的逻辑, 而不是我们常识里只要调用到就可以。
error则是被弱化了,只是函数的一个返回值,提示而已,没有抛出的概念。
如果发生了panic,没有被recover处理,则会导致整个程序崩溃,这点有点不友好,不够健壮,可能是使用协成的缘故。

先后顺序带来的影响

可能我们觉得的代码块儿,先后都一样,但是实际却天差地别,还容易产生bug。

func Heart(){
	defer HandlePanic()
	ch :=make(chan int, 10)
	for i:=0;i<10;i++{
		close(ch)
	}
	// defer HandlePanic()  // recover()放置在后面
}
func HandlePanic() {
	if r := recover(); r != nil {
		fmt.Println("panic可控不影响,继续执行")
	}
}

这个短小的代码,如果recover放置在后面,则捕获不到panic。不知道为啥,编译器为啥不在编译时把defer代码块放前面呢?

	for val := range ch {
		fmt.Println(val)
	}
	// 另外一个协程中执行
    close(ch)
}

如果先执行了close(ch)则for不会阻塞,后执行,虽然ch关闭了,但是for语句依然会阻塞,并不会退出。

nil和零值

可能开始会很奇怪,nil为什么不叫通用的null?代码写得多了,发现还真不一样。null和nil都可以赋值给引用对象,但是在null可以作为实参传入函数中,nil却不可以。如下,含义都是去关闭一个为零值的channel,但是第二种方式报错,原因在于nil是带有类型的,不能脱离类型使用。

	var ch1 chan int = nil
	close(ch1)
	close(nil) // 报错
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值