如果未找到行,则QueryRow()。Scan()返回错误。 怎么解决?

I have spent a lot of time trying to solve this problem.

I have a struct:

type Token struct {
    Id             *int64     `db:"id"`
    Email          *string    `db:"email"`
    OperationType  *string    `db:"operation_type"`
    Token          *string    `db:"token"`
    ExpirationDate *time.Time `db:"expiration_date"`
}

I have a function which finds one token by email:

func (r Repo2) FindOneByEmail(ctx context.Context, email string, ct *Token) error {
    row := r.DB.QueryRow(`
        SELECT id, email, operation_type, token, expiration_date 
        FROM tokens 
        WHERE email=$1 AND type=$2 AND expiration_date>$3::date`,
        email, "registration", time.Now(),
    )

    err := row.Scan(&ct.Id, &ct.Email, &ct.OperationType, &ct.Token, &ct.ExpirationDate)
    if err != nil {
        return err
    }

    return nil
}

Some fields in db can be null (that is why I use pointers in struct)

But when I do .Scan, it throws error (as value is null it can't take address "&")

But if I remove "&", It throws error too "invalid memory address or nil pointer dereference"

So how can I solve this problem?

The idea is: If if finds a row, it needs to get fields values, but if row was not found it needs to throw sql.ErrNoRows

Solution for pgx Driver:

Remove pointers from struct

type Token struct {
    Id             int64     `db:"id"`
    Email          string    `db:"email"`
    OperationType  string    `db:"operation_type"`
    Token          string    `db:"token"`
    ExpirationDate time.Time `db:"expiration_date"`
}

Rewrite function

func (r Repo2) FindOneByEmail(ctx context.Context, email string, ct *Token) error {
    var date pgtype.Timestamptz

    row := r.DB.QueryRow(`
        SELECT id, email, operation_type, token, expiration_date 
        FROM tokens 
        WHERE email=$1 AND type=$2 AND expiration_date>$3::date`,
        email, "registration", time.Now().UTC(),
    )

    err := row.Scan(&ct.Id, &ct.Email, &ct.OperationType, &ct.Token, &date)
    if err != nil {
        return err
    }

    ct.ExpirationDate = date.Time

    return nil
}