go语言中的try、catch、throw实现

func (o *MsSqlUtils) ExecuteSql(cmd string) (err1 error, affected int64) {
	defer func() { //必须要先声明defer,否则不能捕获到panic异常
		if err2 := recover(); err2 != nil {
			err1 = fmt.Errorf("internal error: %v", err2)
		}
	}()
	stmt, err := o.Db.Prepare(cmd)
	checkErr(err)
	var res sql.Result
	res, err1 = stmt.Exec()
	checkErr(err1)
	if err1 != nil {
		affected, err1 = res.RowsAffected()
	}
	return
}

函数中的defer中调用了recover(),获取错误,并作为函数的返回值。

go中很多函数有error类型的返回值,如果希望以异常的形式抛出,可以调用panic让recover函数捕获,如:

func (o *MsSqlUtils) ExecuteWithTrans(callback TransCallback) (err1 error) {
	defer func() { //必须要先声明defer,否则不能捕获到panic异常
		if err2 := recover(); err2 != nil {
			err1 = fmt.Errorf("internal error: %v", err2)
		}
	}()
	trans, _ := o.Db.Begin()
	err := callback(o)
	if err == nil {
		trans.Commit()
	} else {
		trans.Rollback()
		panic(err)
	}
	return
}

这里callback是函数调用者编写的函数,如果其中有错误发生,则使用panic抛出异常,让上面的recover捕获。

或采用网上的封装,模拟C++的方式:

package try

import "reflect"

// Try catches exception from f
func Try(f func()) *tryStruct {
    return &tryStruct{
        catches: make(map[reflect.Type]ExeceptionHandler),
        hold:    f,
    }
}

// ExeceptionHandler handle exception
type ExeceptionHandler func(interface{})

type tryStruct struct {
    catches map[reflect.Type]ExeceptionHandler
    hold    func()
}

func (t *tryStruct) Catch(e interface{}, f ExeceptionHandler) *tryStruct {
    t.catches[reflect.TypeOf(e)] = f
    return t
}

func (t *tryStruct) Finally(f func()) {
    defer func() {
        if e := recover(); nil != e {
            if h, ok := t.catches[reflect.TypeOf(e)]; ok {
                h(e)
            } else {
                f()
            }
        }
    }()

    t.hold()
}

//demo
import (
    "log"
    "try"
)

func main() {
    try.Try(func() {
        panic("123")
    }).Catch(1, func(e interface{}) {
        log.Println("int", e)
    }).Catch("", func(e interface{}) {
        log.Println("string", e)
    }).Finally(func() {
        log.Println("finally")
    })
}

 

你可能感兴趣的:(go)