如何在Go语言中模拟try/catch,且保留数据库错误上下文信息?
在Go中实现带数据库文件信息的批量SQL执行错误处理
场景回顾
Java里可以用try/catch批量执行SQL,捕获异常时直接带上数据库文件的信息,代码简洁还能定位问题:
db.Attach(dbFile) try { db.Exec(sql1); db.Exec(sql2); db.Exec(sql3); } catch (SQLException e) { throw new Error("sql error in executing " + dbFile + " ", e); }
但在Go里,要是逐个判断db.Exec的错误,代码会变得很冗余:
db.Attach(dbFile) var err error if err = db.Exec(sql1); err != nil { log.Panic(fmt.Sprintf("error in attaching db %s error : %s", dbFile, err)) } if err = db.Exec(sql2); err != nil { log.Panic(fmt.Sprintf("error in attaching db %s error : %s", dbFile, err)) } if err = db.Exec(sql3); err != nil { log.Panic(fmt.Sprintf("error in attaching db %s error : %s", dbFile, err)) }
用db.MustExec虽然能简化代码,但没法在错误信息里带上关联的数据库文件:
db.Attach(dbFile) db.MustExec(sql1) db.MustExec(sql2) db.MustExec(sql3)
下面给几个不冗余、也不用循环SQL切片的解决办法:
解决方案
1. 自定义带数据库标识的MustExec方法
要是你的db是自定义结构体,直接给它加个专属的MustExec方法,把dbFile绑定进去:
type MyDB struct { *sql.DB // 假设原数据库实例是sql.DB dbFile string } func (m *MyDB) MustExec(query string, args ...interface{}) { _, err := m.Exec(query, args...) if err != nil { log.Panicf("执行数据库%s出错: %v", m.dbFile, err) } } // 用的时候这样写 db := &MyDB{DB: originalDB, dbFile: dbFile} db.Attach(dbFile) db.MustExec(sql1) db.MustExec(sql2) db.MustExec(sql3)
2. 用闭包临时包装
不想改原DB结构体的话,用闭包快速封装一个带dbFile的执行函数就行,主代码依然简洁:
db.Attach(dbFile) // 封装一个带dbFile的mustExec mustExec := func(query string, args ...interface{}) { _, err := db.Exec(query, args...) if err != nil { log.Panicf("执行数据库%s出错: %v", dbFile, err) } } // 直接调用就行 mustExec(sql1) mustExec(sql2) mustExec(sql3)
3. 用defer+recover模拟try/catch
要是想更贴近Java的try/catch模式,用Go的defer+recover机制,把批量执行逻辑包在一个函数里,捕获panic后加上dbFile信息:
func execWithDB(db *sql.DB, dbFile string, sqls ...string) { defer func() { if r := recover(); r != nil { // 把捕获到的错误重新包装,带上dbFile err, ok := r.(error) if !ok { err = fmt.Errorf("%v", r) } log.Panicf("数据库%s执行SQL出错: %v", dbFile, err) } }() // 这里虽然用了循环,但主逻辑里不用写,也不算冗余 for _, sql := range sqls { db.MustExec(sql) } } // 使用方式 db.Attach(dbFile) execWithDB(db, dbFile, sql1, sql2, sql3)
内容的提问来源于stack exchange,提问作者Demeter P. Chen
相关产品推荐
相关产品推荐

