版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
Go中如何写try...catch...
go中是没有try...catch...语法的,但是仍提供了实现类似功能的panic、defer、recover函数来实现try...catch...。那么具体该如何实现呢?我们就从一个小目标开启实验之旅。实验目标:异常时正确返回期望的结构体数据
panic、defer、recover实验
1. 设计实验代码
package main
import "fmt"
type TxInfo struct {
ChainId string `json:"chainId"`
Hash string `json:"hash"`
BlockHash string `json:"blockHash"`
}
func main() {
ti := TxInfo{
ChainId: "1",
Hash: "0x86a5a6074cce7d1f418b41f363a22e64426dba10039f120832af064c8aa1266f",
}
ri := &TxInfo{
ChainId: "1",
Hash: "0x86a5a6074cce7d1f418b41f363a22e64426dba10039f120832af064c8aa1266f",
}
fmt.Println("Test1 Start:=======================")
ni := parserValue(ti)
fmt.Println("ni", ni)
fmt.Println("ti", ti)
fmt.Println("Test2 Start:=======================")
nj := parserValue1(ti)
fmt.Println("nj", nj)
fmt.Println("ti", ti)
fmt.Println("Test3 Start:=======================")
ti = normalValue(ti)
fmt.Println("ti", ti)
fmt.Println("Test4 Start:=======================")
parserReference(ri)
fmt.Println("ri", *ri)
}
func normalValue(ti TxInfo) TxInfo {
//保留的还是初识栈的值
defer handleExceptionValue(ti)
ti.BlockHash = "14972319"
//说明了这不是一个原子操作,进行了成功赋值
return ti
}
func parserValue(ti TxInfo) TxInfo {
//保留的还是初识栈的值
defer handleExceptionValue(ti)
ti.BlockHash = "14972317"
//尽管handleExcpetionValue中有return 副本的变量,但是parserValue并没有通过return进行赋值返回,所以parserValue返回ni { }
panic("parserValue error")
}
//通过指定返回变量t的方式,就不需要在用return了,因为已经包含了赋值+return功能了
func parserValue1(ti TxInfo) (t TxInfo) {
//保留的还是初识栈的值
defer handleExceptionValue(ti) //如果这里是ti的话,handleExceptionValue打印的是当前对象{1 0x86a5a6074cce7d1f418b41f363a22e64426dba10039f120832af064c8aa1266f }
//defer handleExceptionValue(t) //如果这里是t的话,目前t还是空对象,所以handleExceptionValue打印的是{}
//defer handleExceptionNoRecover(ti) //因为里面不包含recover()函数,所以整个服务就停止运行;和没有defer的效果是一样的
//改为变量赋值的方式来返回
t = ti
t.BlockHash = "14972311"
fmt.Println("Inner ti:", ti) // {1 0x86a5a6074cce7d1f418b41f363a22e64426dba10039f120832af064c8aa1266f } 说明是值传递,即t的改变并未改变ti
fmt.Println("Inner t:", t) //{1 0x86a5a6074cce7d1f418b41f363a22e64426dba10039f120832af064c8aa1266f 14972311}
panic("parserValue1 error")
}
//对于引用,无需返回,不惧怕中间繁盛Panic导致的还未赋值,推荐的做法
func parserReference(ri *TxInfo) {
defer handleExceptionReference("parserReference")
ri.BlockHash = "14972318"
panic("parserReference error")
}
func handleExceptionNoRecover(ti TxInfo) TxInfo {
fmt.Println(ti, "handleExceptionNoRecover-Recover:", ti)
return ti
}
func handleExceptionValue(ti TxInfo) TxInfo {
if r := recover(); r != nil {
fmt.Println(ti, "handleExceptionValue-Recover:", r)
}
return ti
}
func handleExceptionReference(funcname string) {
if r := recover(); r != nil {
fmt.Println(funcname, "handleExceptionReference-Recover:", r)
}
}
2. 实验代码运行输出
Test1 Start:=======================
{
1 0x86a5a6074cce7d1f418b41f363a22e64426dba10039f120832af064c8aa1266f } handleExceptionValue-Recover: parserValue error
ni {
}
ti {
1 0x86a5a6074cce7d1f418b41f363a22e64426dba10039f120832af064c8aa1266f }
Test2 Start:=======================
Inner ti: {
1 0x86a5a6074cce7d1f418b41f363a22e64426dba10039f120832af064c8aa1266f }
Inner t: {
1 0x86a5a6074cce7d1f418b41f363a22e64426dba10039f120832af064c8aa1266f 14972311}
{
1 0x86a5a6074cce7d1f418b41f363a22e64426dba10039f120832af064c8aa1266f } handleExceptionValue-Recover: parserValue1 error
nj {
1 0x86a5a6074cce7d1f418b41f363a22e64426dba10039f120832af064c8aa1266f 14972311}
ti {
1 0x86a5a6074cce7d1f418b41f363a22e64426dba10039f120832af064c8aa1266f }
Test3 Start:=======================
ti {
1 0x86a5a6074cce7d1f418b41f363a22e64426dba10039f120832af064c8aa1266f 14972319}
Test4 Start:=======================
parserReference handleExceptionReference-Recover: parserReference error
ri {
1 0x86a5a6074cce7d1f418b41f363a22e64426dba10039f120832af064c8aa1266f 14972318}