使用go-sql-driver时,如何区分连接错误和其他错误

时间:2016-01-29 09:45:21

标签: go

func mainloop(db *sql.DB) {
        type pushTask struct {
            TaskId string
            Uri    string
        }

        stmt, err := db.Prepare("INSERT INTO ErrPushCache(TaskId, Uri) VALUES(?, ?)")
        if err != nil {
            log.Fatal("db.Prepare Failed ", err)
        }

        var (
            mysqlOk bool = true
            task    pushTask
        )
        for {
            task.TaskId = RandStringRunes(8)
            task.Uri = RandStringRunes(16)

            res, err := stmt.Exec(task.TaskId, task.Uri)
            if err != nil {
                if err == driver.ErrBadConn {
                    if mysqlOk {
                        log.Print("Connection with mysql seems down, %s", err.Error())
                        mysqlOk = false
                        os.Exit(1)
                    }
                } else {
                    log.Print("Exec failed ", err)
                }

                time.Sleep(2 * time.Second)
                continue
            }
            if !mysqlOk {
                log.Print("Connection with mysql is ok now")
                mysqlOk = true
            }
            lastId, err := res.LastInsertId()
            if err != nil {
                log.Print("LastInsertId failed ", err)
            }
            rowCnt, err := res.RowsAffected()
            if err != nil {
                log.Print("RowsAffected failed ", err)
            }
            log.Printf("ID = %d, affected = %d\n", lastId, rowCnt)

            time.Sleep(20 * time.Second)
        }
    }

    func main() {
        db, err := sql.Open("mysql",
            "rench:ren123@tcp(192.168.1.61:3306)/hunanTV")
        if err != nil {
            log.Fatal("sql.Open Failed ", err)
        }

        mainloop(db)

        defer db.Close()
    }

在mainloop函数中,如果mysql和客户端之间的连接中断,stmt.Exec将失败,它将返回错误,如何区分连接错误与其他错误。(错误== driver.ErrBadConn总是假)。

如果连接断开,则日志为:

2016/01/29 17:21:31执行失败拨号tcp 192.168.1.61:3306:getsockopt:连接被拒 2016/01/29 17:21:33执行失败拨号tcp 192.168.1.61:3306:getsockopt:连接被拒 2016/01/29 17:21:35执行失败拨号tcp 192.168.1.61:3306:getsockopt:连接被拒 2016/01/29 17:21:37执行失败拨号tcp 192.168.1.61:3306:getsockopt:连接被拒 2016/01/29 17:21:39执行失败拨号tcp 192.168.1.61:3306:getsockopt:连接被拒绝

...

2 个答案:

答案 0 :(得分:0)

网络错误将是满足net.Error接口的类型。

if err, ok := err.(net.Error); ok {
    log.Println("network error:", err)
} else {
    log.Println("other error:", err)
}

在大多数情况下,它并不重要,因为某些原因导致操作失败,无论如何都需要处理它。只有当您想根据您确实需要检查的网络错误采取不同的操作时。

答案 1 :(得分:-1)

这就是go的错误处理真的困扰我的地方。大多数情况下,实际的错误类型没有记录,所以你必须通过源代码并检查代码可以返回哪些错误。在某些情况下,这些只是通用字符串错误,因为代码是特定于平台的,因此错误也是特定于平台的。

您可以这样做,检查源代码,或者您可以打印错误类型以确切知道它是哪一个。

log.Printf("%T", err)