douhui3305 2019-08-10 18:21
浏览 235
已采纳

如果未找到行,则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

  • 写回答

1条回答 默认 最新

  • dongzhangji4824 2019-08-10 19:51
    关注

    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
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 Vue3 大型图片数据拖动排序
  • ¥15 划分vlan后不通了
  • ¥15 GDI处理通道视频时总是带有白色锯齿
  • ¥20 用雷电模拟器安装百达屋apk一直闪退
  • ¥15 算能科技20240506咨询(拒绝大模型回答)
  • ¥15 自适应 AR 模型 参数估计Matlab程序
  • ¥100 角动量包络面如何用MATLAB绘制
  • ¥15 merge函数占用内存过大
  • ¥15 使用EMD去噪处理RML2016数据集时候的原理
  • ¥15 神经网络预测均方误差很小 但是图像上看着差别太大