Trabajar con una base de datos SQL en Go

En este artículo, enumero cómo realizar operaciones comunes de bases de datos SQL con Go.

Presentandodatabase/sql

Go ofrece una API limpia de base de datos SQL en su biblioteca estándardatabase/sqlpaquete, pero los controladores de base de datos específicos deben instalarse por separado.

Es un enfoque inteligente porque proporciona una interfaz común que implementan casi todos los controladores de base de datos.

Si desea utilizar MySQL, puede utilizarhttps://github.com/go-sql-driver/mysql.

Si está usando PostgreSQL, usehttps://github.com/lib/pq.

Solo necesitas incluir la lib usandoimport _, y eldatabase/sqlLa API se configurará para habilitar ese controlador:

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

Abra la conexión a la base de datos

Aunque el objetivo es abstraerlo, todavía existen diferencias en algunas cosas, por ejemplo, en cómo se conecta a una base de datos:

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) }

pero gran parte de la API real es independiente de la base de datos y se puede intercambiar con bastante facilidad (aquí no se habla de SQL, solo se hace referencia a la API de la base de datos).

Cerrar la conexión a la base de datos

Cuando tenga sentido, siempre debe cerrar la conexión a la base de datos.

Puede usarlo como de costumbredeferpara cerrarlo cuando finalice la función que abre la conexión db:

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

Extraer datos de la base de datos

Seleccione una sola fila

La consulta de una tabla se realiza en 2 pasos. Primero llamasdb.QueryRow(), entonces llamasScan()en el resultado.

Ejemplo:

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()se utiliza para consultar un solo valor de una tabla.

Firma:

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

Devuelve un puntero a undb.Rowvalor.

(*Row) Scanescanea la fila, copiando los valores de la columna al parámetro que se le ha pasado.

Firma:

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

Si se devolvió más de una fila, solo escanea la primerae ignore el resto.

Si no se devolvió ninguna fila, devuelve unErrNoRowserror.

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

Seleccionar varias filas

Para consultar una sola fila usamosdb.QueryRow(). Para consultar varias filas usamosdb.Query(), que devuelve un*Rowsvalor.

De los documentos:

//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 devuelve el error, si lo hay, que se encontró durante la iteración. // Se puede llamar a Err después de un cierre explícito o implícito.

Necesitamos iterar sobrerows.Next(), que nos permite llamarrows.Scan()en el bucle.

Si surge algún error al preparar la siguiente fila, el ciclo finaliza y podemos obtener el error llamandorows.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)
}

Más tutoriales de go: