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

时间:2019-08-10 18:21:26

标签: sql postgresql go

我花了很多时间尝试解决这个问题。

我有一个结构:

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"`
}

我有一个可以通过电子邮件找到一个令牌的功能:

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
}

db中的某些字段可以为null(这就是为什么我在struct中使用指针的原因)

但是,当我执行.Scan时,它会引发错误(由于值为null,因此无法使用地址“&”)

但是如果我删除“&”,它也会引发错误“无效的内存地址或nil指针取消引用”

那我该如何解决这个问题?

想法是:如果找到行,则需要获取字段值,但是如果找不到行,则需要抛出sql.ErrNoRows

1 个答案:

答案 0 :(得分:1)

pgx驱动程序解决方案:

从结构中删除指针

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"`
}

重写功能

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
}