0
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()
    }

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

...

2 Answers 2

2

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.

Sign up to request clarification or add additional context in comments.

2 Comments

True, but in some cases it does matter. In a webapp, we could return http:503 for network error, while 500 for db error.
@MopparthyRavindranath: those are not errors, those are http status codes, and have nothing to do with the error value returned from the network connection.
0

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)

3 Comments

This is isn't an error handling problem, it's a documentation problem. An unexpected error type is no different than an unexpected exception type bubbling up, except in the former case you know you're getting something.
I know that it's a problem with documentation. The real problem is that golang supplied packages has that problem and because of that most of third-party packages inherently has that problem. If I want to take different actions depending on error type most of the time I have to go through the source code. And in some cases I find code like errors.New() which is just useless exactly like new Exception() is useless. And that's what bothering me - golang documentation doesn't suggest that it's a good thing to document returned errors. That's not the case with exception-based languages
But there is also a error handling problem. error interface hides what kind of error it is. And because errors in Go has to be explicitly handled (because they're ignored by default and not enforced by any means) you don't know the type and value until you print it. In contrast with exceptions where program will crash and display you nice crash report. And that's exactly what we are seeing here - some error popped up, just printing it is useless. Don't get me wrong, I like Go very much but not it's C-like error handling. At least we can do this github.com/facebookgo/stackerr

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.