Подготовленные операторы
Выполняйте параметризованные запросы
«Подготовленные операторы» — бесплатный урок Go Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Go Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Go Academy содержит 4 уроков всего.
Что такое подготовленный оператор
Подготовленный оператор один раз отправляет текст SQL в базу данных для разбора и построения плана, а затем многократно выполняется с разными параметрами. Это быстрее при повторяющихся запросах и защищает от внедрения кода.
Заполнители параметров
Никогда не формируйте SQL конкатенацией пользовательского ввода. Используйте заполнители, чтобы драйвер передавал значения отдельно. PostgreSQL использует $1, $2, а MySQL и SQLite — ?.
SELECT * FROM users WHERE age > $1 AND city = $2Почему это предотвращает внедрение
Поскольку параметры передаются отдельно от текста SQL, база данных обрабатывает их только как данные, а не как код. Вредоносное значение вроде " OR 1=1 становится строковым литералом, а не исполняемым SQL-кодом.
db.Prepare
Prepare возвращает объект *sql.Stmt, связанный с пулом. Затем вызывайте Exec или Query для этого оператора, передавая аргументы.
stmt, err := db.Prepare("INSERT INTO users(name, age) VALUES($1, $2)")
if err != nil {
log.Fatal(err)
}
defer stmt.Close()Выполнение оператора
Вызовите stmt.Exec, передав аргумент для каждого заполнителя. Для вставок и обновлений Exec возвращает объект sql.Result с числом затронутых строк и ID последней вставленной записи.
res, err := stmt.Exec("Ada", 36)
if err != nil {
log.Fatal(err)
}
n, _ := res.RowsAffected()
fmt.Println("inserted", n)Повторное использование в цикле
Преимущество достигается за счёт повторного использования: подготовьте оператор один раз и многократно выполняйте его внутри цикла. База данных повторно использует разобранный план при каждом вызове.
for _, u := range users {
if _, err := stmt.Exec(u.Name, u.Age); err != nil {
log.Fatal(err)
}
}Неявная подготовка
Прямая передача аргументов в db.Query или db.Exec также безопасно использует заполнители; драйвер может выполнять подготовку внутри себя. Явный Prepare в основном нужен для многократного выполнения.
Рабочая симуляция привязки параметров
Для настоящих подготовленных выражений нужна база данных. Этот запускаемый пример моделирует безопасную привязку параметров и показывает, как значения остаются отделёнными от текста запроса.
package main
import "fmt"
func execPrepared(query string, args ...interface{}) string {
return fmt.Sprintf("EXEC %q with args %v", query, args)
}
func main() {
q := "INSERT INTO users(name, age) VALUES($1, $2)"
people := [][2]interface{}{{"Ada", 36}, {"Lin", 41}}
for _, p := range people {
fmt.Println(execPrepared(q, p[0], p[1]))
}
}Варианты с контекстом
Используйте PrepareContext и stmt.ExecContext, чтобы подготовленные вызовы учитывали ограничения времени и отмену, как и остальные операции database/sql.
Всегда закрывайте подготовленное выражение
Объект *sql.Stmt удерживает ресурсы базы данных. После завершения работы отложите вызов stmt.Close(). Утечки выражений могут исчерпать серверное ограничение на число подготовленных выражений.
Выражения и пул соединений
Выражение, подготовленное для *sql.DB, работает с соединениями из пула; библиотека заново подготавливает его на том соединении, на котором оно окажется. Обычно Вам не нужно управлять этим самостоятельно.
Быстрая проверка
Проверьте свои знания о подготовленных выражениях.
Итоги
Вы изучили подготовленные выражения:
- Prepare разбирает запрос один раз, а выполняет его много раз
- Заполнители ($1 или ?) сохраняют значения как данные и предотвращают внедрение
- Вызов Exec возвращает число затронутых строк; используйте отложенный вызов stmt.Close()
- Повторно используйте выражения в циклах; для крайних сроков используйте варианты с контекстом
Часто задаваемые вопросы
Урок «Подготовленные операторы» бесплатный?
Да — полный текст урока «Подготовленные операторы» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Go Academy, подпишись на CoddyKit PRO. Курс Go Academy содержит 4 уроков всего.
Чему я научусь в уроке «Подготовленные операторы»?
Выполняйте параметризованные запросы Ты практикуешь Go Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Go Academy?
Предыдущий опыт не требуется. Go Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.
Сколько времени занимает урок «Подготовленные операторы»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Go Academy?
Да. Каждый урок Go Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Открытие соединения
- Запрос строк
- Подготовленные операторы
- Транзакции