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 深度学习残差模块模型
  • ¥20 两个不同Subnet的点对点连接
  • ¥50 怎么判断同步时序逻辑电路和异步时序逻辑电路
  • ¥15 差动电流二次谐波的含量Matlab计算
  • ¥15 Can/caned 总线错误问题,错误显示控制器要发1,结果总线检测到0
  • ¥15 C#如何调用串口数据
  • ¥15 MATLAB与单片机串口通信
  • ¥15 L76k模块的GPS的使用
  • ¥15 请帮我看一看数电项目如何设计
  • ¥23 (标签-bug|关键词-密码错误加密)