database/sql
在一些地方,错误行为是特殊情况,或者您可能需要了解一些额外信息。
来自迭代结果集产生的错误考虑以下代码:
for rows.Next() {
// ...
}
if err = rows.Err(); err!= nil {
// 在这里处理错误
}
rows.Err()rows.Next()rows.Close()
来自关闭结果集产生的错误
sql.Rows
for rows.Next() {
// ...
break; // 糟糕,行未关闭!内存泄漏...
}
// 执行通常的 "if err = rows.Err()" [此处省略] ...
// 在这里 [re?] 关闭总是安全的:
if err = rows.Close(); err != nil {
// 但是如果出现错误该怎么办?
log.Println(err)
}
rows.Close()rows.Close()
来自 QueryRow() 的错误
考虑以下获取单行的代码:
var name string
err = db.QueryRow("select name from users where id = ?", 1).Scan(&name)
if err != nil {
log.Fatal(err)
}
fmt.Println(name)
id = 1.Scan()name
sql.ErrNoRowsQueryRow()
Scan()
var name string
err = db.QueryRow("select name from users where id = ?", 1).Scan(&name)
if err != nil {
if err == sql.ErrNoRows {
//没有行,但也没有错误发生
} else {
log.Fatal(err)
}
}
fmt.Println(name)
QueryRow()QueryRow()Scan()
QueryRow()
识别特定的数据库错误
编写如下代码可能很有诱惑力:
rows, err := db.Query("SELECT someval FROM sometable")
// 错误包含:
// ERROR 1045 (28000):Access denied for user 'foo'@'::1' (using password: NO)
if strings.Contains(err.Error(), "Access denied") {
// 处理被拒绝的错误
}
然而,这并不是最好的方法。例如,字符串值可能会有所不同,具体取决于服务器使用哪种语言发送错误消息。最好通过比较错误编号来确定具体的错误是什么。
database/sql
if driverErr, ok := err.(*mysql.MySQLError); ok { // 现在可以直接访问错误编号
if driverErr.Number == 1045 {
// 处理被拒绝的错误
}
}
MySQLError.Number
pq
if driverErr, ok := err.(*mysql.MySQLError); ok {
if driverErr.Number == mysqlerr.ER_ACCESS_DENIED_ERROR {
// 处理被拒绝的错误
}
}
处理连接错误
如果您与数据库的连接被删除、终止或出现错误怎么办?
database/sql
kill