Работа с базой данных SQL в Go

В этой статье я перечисляю, как выполнять стандартные операции с базой данных SQL с помощью Go.

Представляемdatabase/sql

Go предлагает чистый API базы данных SQL в своей стандартной библиотекеdatabase/sqlпакет, но определенные драйверы базы данных должны быть установлены отдельно.

Это разумный подход, поскольку он предоставляет общий интерфейс, который реализует почти каждый драйвер БД.

Если вы хотите использовать MySQL, вы можете использоватьhttps://github.com/go-sql-driver/mysql.

Если вы используете PostgreSQL, используйтеhttps://github.com/lib/pq.

Вам просто нужно включить библиотеку, используяimport _, иdatabase/sqlAPI будет настроен для включения этого драйвера:

import "database/sql"
import _ "github.com/go-sql-driver/mysql"

Откройте соединение с базой данных

Хотя цель состоит в том, чтобы сделать его абстрагированным, все же есть различия в некоторых вещах, например, в том, как вы подключаетесь к базе данных:

import "database/sql"
import _ "github.com/go-sql-driver/mysql"

//… db, err := sql.Open(“mysql”, “theUser:[email protected]/theDbName”) if err != nil { panic(err) }

import “database/sql”
import _ github.com/lib/pq

//… db, err := sql.Open(“postgres”, “user=theUser dbname=theDbName sslmode=verify-full”) if err != nil { panic(err) }

но большая часть фактического API не зависит от базы данных и может быть легко заменена (не говоря уже о SQL, просто ссылаясь на API базы данных).

Закройте соединение с базой данных

Там, где это имеет смысл, всегда следует закрывать соединение с базой данных.

Вы можете как обычно использоватьdeferчтобы закрыть его, когда функция, открывающая соединение с БД, завершится:

db, err := sql.Open("postgres", psqlInfo)
defer db.Close()

Извлечь данные из базы данных

Выберите одну строку

Запрос таблицы выполняется в 2 этапа. Сначала вы звонитеdb.QueryRow(), тогда вы звонитеScan()по результату.

Пример:

id := 1
var col string
sqlStatement := `SELECT col FROM my_table WHERE id=$1`
row := db.QueryRow(sqlStatement, id)
err := row.Scan(&col)
if err != nil {
    if err == sql.ErrNoRows {
        fmt.Println("Zero rows found")
    } else {
        panic(err)
    }
}

db.QueryRow()используется для запроса одного значения из таблицы.

Подпись:

func (db *DB) QueryRow(query string, args ...interface{}) *Row

Он возвращает указатель наdb.Rowценить.

(*Row) Scanсканирует строку, копируя значения столбца в переданный в нее параметр.

Подпись:

func (r *Row) Scan(dest ...interface{}) error

Если было возвращено более одной строки, сканируется только первая.а остальное игнорировать.

Если строка не была возвращена, возвращаетсяErrNoRowsошибка.

var ErrNoRows = errors.New("sql: no rows in result set")

Выбрать несколько строк

Для запроса одной строки мы использовалиdb.QueryRow(). Для запроса нескольких строк мы используемdb.Query(), который возвращает*Rowsценить.

Из документов:

//Rows is the result of a query. Its cursor starts before  the first row of the result set. Use Next to advance through the rows:

    rows, err := db.Query("SELECT ...")
    ...
    defer rows.Close()
    for rows.Next() {
        var id int
        var name string
        err = rows.Scan(&id, &name)
        ...
    }
     err = rows.Err() // get any error encountered ing iteration
    ...

// Err возвращает ошибку, если таковая имеется, которая была обнаружена во время итерации. // Err может вызываться после явного или неявного закрытия.

Нам нужно повторитьrows.Next(), что позволяет нам звонитьrows.Scan()в петлю.

Если при подготовке следующей строки возникает какая-либо ошибка, цикл завершается, и мы можем получить ошибку, вызвавrows.Err():

type Timeline struct {
    Id int
    Content string
}
rows, err := db.Query(`SELECT id, content FROM timeline`)
if err != nil {
    panic(err)
}
defer rows.Close()
for rows.Next() {
    timeline := Timeline{}
    err = rows.Scan(&timeline.Id, &timeline.Content)
    if err != nil {
        panic(err)
    }
    fmt.Println(timeline)
}
err = rows.Err()
if err != nil {
    panic(err)
}

Больше руководств по go: