Использование подготовленных операторов и указателей в Golang

В MySQL вы можете использовать вопросительный знак (?) в подготовленном операторе для обозначения значения.

func GetUserId(name string) (int, error) {
  stmt, err := dbconn.Db.Prepare(`SELECT id FROM user
    WHERE name="?";`) // (1) - BAD
  stmt, err := dbconn.Db.Prepare(`SELECT id FROM user
    WHERE name=?;`) // (2) – GOOD
  if err != nil {
    log.Fatal(err)
  }
  defer stmt.Close()

  var userId int
  err = stmt.QueryRow(name).Scan(&userId) // (3)
  if err != nil {
    if err != sql.ErrNoRows {
      log.Fatal(err)
    }
    return 0, err
  }
  return userId, nil
}
Вход в полноэкранный режим Выход из полноэкранного режима

В приведенном выше коде Go, dbconn — это соединение с сервером MySQL. В строке 1 определяется подготовленный оператор. А строка 3 запрашивает таблицу на наличие строки, в которой столбец name совпадает со значением переменной name. Я предположил, что ? в этом запросе будет интерполироваться с фактической строкой. Я добавил кавычки, так как они необходимы вокруг строк в MySQL CLI.

В результате ничего не возвращается. Удаление кавычек решило проблему. Правильный код находится в строке 2.

Я также нахожу строку 3 довольно интересной. Здесь, во-первых, stmt.QueryRow() возвращает указатель на объект sql.Row. Затем его метод Scan() делает две интересные вещи: a) устанавливает «dest» в выходное значение и b) возвращает ошибку, если есть ошибка, или nil, если ошибки нет.

Тонкость a весьма интересна. В этом случае метод Scan() найдет в памяти адрес переменной userId и запишет туда выходное значение (ID пользователя).

Такое ощущение, что получение значения из БД является побочным эффектом.

То же самое происходит при декодировании строки JSON. В данном примере, в строке 4, метод Unmarshal() распаковывает строку JSON и записывает ее в &animals, адрес переменной animals. И это побочный эффект. Возвращаемое значение опять же либо ошибка, либо nil — если есть ошибка, то игнорировать ее просто нельзя.

var jsonBlob = []byte(`[
    {"Name": "Platypus", "Order": "Monotremata"},
    {"Name": "Quoll",    "Order": "Dasyuromorphia"}
]`)
type Animal struct {
    Name  string
    Order string
}
var animals []Animal
// (4)
err := json.Unmarshal(jsonBlob, &animals)
Вход в полноэкранный режим Выход из полноэкранного режима

Оцените статью
devanswers.ru
Добавить комментарий