SQL Next не продвигает курсор

#sql #go #go-sqlmock

#sql #Вперед #go-sqlmock

Вопрос:

У меня есть функция, которую я использовал для перебора результирующего набора из запроса:

 func readRows(rows *sql.Rows, translator func(*sql.Rows) error) error {
    defer rows.Close()

    // Iterate over each row in the rows and scan each; if an error occurs then return
    for shouldScan := rows.Next(); shouldScan; {
        if err := translator(rows); err != nil {
            return err
        }
    }

    // Check if the rows had an error; if they did then return them. Otherwise,
    // close the rows and return an error if the close function fails
    if err := rows.Err(); err != nil {
        return err
    }

    return nil
}
  

translator Функция в первую очередь отвечает за вызов Scan для *sql.Rows объекта. Примером этого является:

 readRows(rows, func(scanner *sql.Rows) error {
    var entry gopb.TestObject

    // Embed the variables into a list that we can use to pull information out of the rows
    scanned := []interface{}{...}

    if err := scanner.Scan(scanned...); err != nil {
        return err
    }

    entries = append(entries, amp;entry)
    return nil
})
  

Я написал модульный тест для этого кода:

 // Create the SQL mock and the RDS reqeuster
db, mock, _ := sqlmock.New()
requester := Requester{conn: db}
defer db.Close()

// Create the rows we'll use for testing the query
rows := sqlmock.NewRows([]string{"id", "data"}).
                AddRow(0, "data")

// Verify the command order for the transaction
mock.ExpectBegin()
mock.ExpectQuery(regexp.QuoteMeta("SELECT `id`, `data`, FROM `data`")).WillReturnRows(rows)
mock.ExpectRollback()

// Attempt to get the data
data, err := requester.GetData(context.TODO())
  

Однако, похоже, что Next вызывается бесконечно. Я не уверен, является ли это sqlmock проблемой или проблема с моим кодом. Буду признателен за любую помощь.

Комментарии:

1. Используйте for rows.Next() { .

2. … это потому, что for <init>; <cond>; <post> { форма for инструкции выполняет <init> , как следует из ее названия, только один раз. В качестве альтернативы вы могли бы использовать for shouldScan := rows.Next(); shouldScan; shouldScan = rows.Next() { , хотя я не знаю веской причины для этого.

3. Смотрите golang.org/ref/spec#For_statements для получения дополнительной информации.

4. Извините, я отлаживал это сам и понял, что забыл обновить инвариант цикла. Я изменю его на использование for rows.Next() { вместо