-1

I am trying to compare an sql error in golang using errors.Is(...) method, which is always returning false.

I have declared an error type variable as below.

var ErrNoRows = errors.New("no rows in result set")

Somewhere down the flow, I am trying to compare an error value with the 'ErrNoRows' error, which always returns false.

However, if I print the err in debug mode, it prints as..

(dlv) p err
error(*errors.errorString) *{
        s: "no rows in result set",}

and printing ErrNoRows also returns the same thing.

(dlv) p ErrNoRows
error(*errors.errorString) *{
        s: "no rows in result set",}

But both these objects are not getting equal, when I compare them with Error.Is function.

err := tx.QueryRow(ctx, sqlstmt).Scan(&myvar)
if errors.Is(err, ErrNoRows) {
...
}

The above check always fails. What am I doing wrong here? I am using https://github.com/jackc/pgx for sql operation.

EDIT I have already seen this question (How to compare Go errors)

The above question talks about using errors.Is(...), instead of a naive equal comparision. I followed the advice as per that question thread.

I was getting error because of not knowing that I still had to deal with the same instances of error objects, as was clarified by @mkopriva.

Mopparthy Ravindranath
  • 3,014
  • 6
  • 41
  • 78
  • 2
    Your `ErrNoRows` is a different *instance* of `*errors.errorString` compared to the one returned by `Scan`. It doesn't matter that the string message are the same. The pointer is not the same and therefore the two errors are not considered equal. – mkopriva Nov 26 '22 at 13:29
  • You should compare the error value against the error provided by the package you're using. E.g. if it's `database/sql` then you should use `errors.Is(err, sql.ErrNoRows)`. https://pkg.go.dev/database/sql@go1.19.3#ErrNoRows – mkopriva Nov 26 '22 at 13:30
  • 2
    https://go.dev/play/p/JuYei-4x2Ne (and [this one](https://go.dev/play/p/mtyE5Mrak_U) demonstrates the usefulness of `errors.Is`). – mkopriva Nov 26 '22 at 13:47

1 Answers1

0

Thanks to mkopriva's suggestion, I understand that error objects comparison with the same error instance provided by the original package.

My understanding was that using errors.Is() function might do a deep (attributes comparison), without having to worry about same objects. But as suggested in the comments, it is not the case.

I had to compare the err returned by calling the sql function, with the err object provided by the same package.

err := tx.QueryRow(ctx, sqlstmt).Scan(&myvar)
if errors.Is(err, pgx.ErrNoRows) {
...
}
Mopparthy Ravindranath
  • 3,014
  • 6
  • 41
  • 78