Описание типа Out database/sql
Out может использоваться для извлечения параметров OUTPUT из хранимых процедур. В этом разделе представлены другие типы: RawBytes, Result
Categories:
type Out
type Out struct {
// Dest — указатель на значение, которое будет установлено в качестве результата
// параметра OUTPUT хранящейся процедуры.
Dest any
// In — является ли параметр параметром INOUT. Если да, то входное значение для хранящейся
// процедуры — это разыменованное значение указателя Dest, которое затем заменяется
// выходным значением.
In bool
// содержит отфильтрованные или неэкспортированные поля
}
Out может использоваться для извлечения параметров OUTPUT из хранимых процедур.
Не все драйверы и базы данных поддерживают параметры OUTPUT.
Пример использования:
var outArg string
_, err := db.ExecContext(ctx, «ProcName», sql.Named(«Arg1», sql.Out{Dest: &outArg}))
type RawBytes
type RawBytes []byte
RawBytes — это байтовый срез, который содержит ссылку на память, принадлежащую самой базе данных. После выполнения Rows.Scan в RawBytes срез остается действительным только до следующего вызова Rows.Next, Rows.Scan или Rows.Close.
RawBytes
- это специальный тип в пакете database/sql
, определённый как []byte
, который используется для сканирования данных из базы данных без копирования памяти. Это может быть полезно для оптимизации производительности при работе с большими бинарными данными.
Основные принципы работы с RawBytes
- Временное владение памятью: RawBytes содержит ссылку на память, управляемую драйвером БД, а не на копию данных.
- Ограниченное время жизни: Данные в RawBytes действительны только до следующего вызова методов:
Next()
Scan()
Close()
- Небезопасность: Если сохранить RawBytes и попытаться использовать после вышеуказанных вызовов, это приведёт к неопределённому поведению.
Пример 1: Базовое сканирование
package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
)
func main() {
db, err := sql.Open("mysql", "user:password@/dbname")
if err != nil {
panic(err)
}
defer db.Close()
rows, err := db.Query("SELECT blob_column FROM my_table WHERE id = ?", 1)
if err != nil {
panic(err)
}
defer rows.Close()
for rows.Next() {
var raw sql.RawBytes
if err := rows.Scan(&raw); err != nil {
panic(err)
}
// Используем raw сразу, пока он действителен
fmt.Printf("Data: %s\n", raw)
// Если нужно сохранить данные, нужно сделать копию:
dataCopy := make([]byte, len(raw))
copy(dataCopy, raw)
// Теперь dataCopy можно использовать после rows.Next()
}
}
Пример 2: Сканирование нескольких столбцов
func scanMultipleColumns(db *sql.DB) error {
rows, err := db.Query("SELECT id, name, data FROM documents")
if err != nil {
return err
}
defer rows.Close()
for rows.Next() {
var id int
var name string
var data sql.RawBytes
if err := rows.Scan(&id, &name, &data); err != nil {
return err
}
fmt.Printf("ID: %d, Name: %s, Data length: %d\n", id, name, len(data))
// Обработка данных должна быть здесь
processData(data)
}
return rows.Err()
}
func processData(data []byte) {
// Обработка данных
}
Пример 3: Опасное использование (неправильное)
func incorrectUsage(db *sql.DB) {
rows, err := db.Query("SELECT data FROM large_blobs")
if err != nil {
panic(err)
}
defer rows.Close()
var allData [][]byte
for rows.Next() {
var raw sql.RawBytes
if err := rows.Scan(&raw); err != nil {
panic(err)
}
// ОШИБКА: сохраняем RawBytes, который станет недействительным
allData = append(allData, raw)
}
// Здесь allData содержит недействительные данные!
for _, data := range allData {
fmt.Println(data) // Может привести к панике или неверным данным
}
}
Когда использовать RawBytes
- Для больших бинарных данных, когда копирование нежелательно
- Для временной обработки данных, которые не нужно сохранять
- Когда производительность критична, и вы готовы следить за временем жизни данных
Альтернативы
Если нужно сохранить данные:
var raw sql.RawBytes
var data []byte
rows.Scan(&raw)
data = make([]byte, len(raw))
copy(data, raw)
// Теперь data можно использовать в любом месте
type Result ¶
type Result интерфейс {
// LastInsertId возвращает целое число, сгенерированное базой данных
// в ответ на команду. Обычно это будет из
// столбца «автоинкремент» при вставке новой строки. Не все
// базы данных поддерживают эту функцию, и синтаксис таких
// операторов варьируется.
LastInsertId() (int64, error)
// RowsAffected возвращает количество строк, затронутых
// обновлением, вставкой или удалением. Не все базы данных или драйверы баз данных
// драйвер базы данных может поддерживать эту функцию.
RowsAffected() (int64, error)
}
Результат обобщает выполненную команду SQL.