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

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
", 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()
    }

in the mainloop function, if the connection between mysql and client is broken,stmt.Exec will be failed, it will return a error, how can i distinguish connection error with other errors.(err == driver.ErrBadConn is always false).

if the connection is broken, the log is :

2016/01/29 17:21:31 Exec failed dial tcp 192.168.1.61:3306: getsockopt: connection refused 2016/01/29 17:21:33 Exec failed dial tcp 192.168.1.61:3306: getsockopt: connection refused 2016/01/29 17:21:35 Exec failed dial tcp 192.168.1.61:3306: getsockopt: connection refused 2016/01/29 17:21:37 Exec failed dial tcp 192.168.1.61:3306: getsockopt: connection refused 2016/01/29 17:21:39 Exec failed dial tcp 192.168.1.61:3306: getsockopt: connection refused

...

That's where go's error handling is really bothering me. Most of the time actual error types are not documented so you have to go through the source and check which errors the code can return. And in some cases those are just generic string errors because the code is platform specific and, thus, errors are also platform specific.

You can do that, check the source code, or you can print the error type to know exactly which one it is.

log.Printf("%T", err)

Network errors will be of a type that satisfies the net.Error interface.

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

In most cases it won't really matter, because the action failed for some reason, and you need to handle it regardless. It's only if you want to take a different action based on a network error that you really need to check.