¿Cuál es la forma recomendada de conectarse a MySQL desde Go?

163

Estoy buscando una solución confiable para conectarme a una base de datos MySQL de Go. He visto algunas bibliotecas, pero es difícil determinar los diferentes estados de integridad y mantenimiento actual. No tengo necesidades complicadas, pero me gustaría saber en qué confían las personas o cuál es la solución más estándar para conectarse a MySQL.

Sergi Mansilla
fuente

Respuestas:

263

Hay algunos controladores disponibles, pero solo debe considerar aquellos que implementan la base de datos / sql API como

  • Proporciona una sintaxis limpia y eficiente.
  • asegura que luego pueda cambiar el controlador sin cambiar su código, aparte de la importación y la conexión.

Hay dos controladores rápidos y confiables disponibles para MySQL:

Los utilicé en producción, los programas se están ejecutando durante meses con millones de conexiones sin fallar.

Otros controladores de bases de datos SQL se enumeran en go-wiki .

Importar al usar MyMySQL:

import (
    "database/sql"
    _ "github.com/ziutek/mymysql/godrv"
)

Importar cuando se utiliza Go-MySQL-Driver:

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

Conectando y cerrando usando MyMySQL:

con, err := sql.Open("mymysql", database+"/"+user+"/"+password)
defer con.Close()
// here you can use the connection, it will be closed when function returns

Conexión y cierre con Go-MySQL-Driver:

con, err := sql.Open("mysql", store.user+":"+store.password+"@/"+store.database)
defer con.Close()

Seleccione una fila:

row := con.QueryRow("select mdpr, x, y, z from sometable where id=?", id)
cb := new(SomeThing)
err := row.Scan(&cb.Mdpr, &cb.X, &cb.Y, &cb.Z)

Seleccione varias filas y cree una matriz con resultados:

rows, err := con.Query("select a, b from item where p1=? and p2=?", p1, p2)
if err != nil { /* error handling */}
items := make([]*SomeStruct, 0, 10)
var ida, idb uint
for rows.Next() {
    err = rows.Scan(&ida, &idb)
    if err != nil { /* error handling */}
    items = append(items, &SomeStruct{ida, idb})
}

Insertar:

_, err = con.Exec("insert into tbl (id, mdpr, isok) values (?, ?, 1)", id, mdpr)

Verá que trabajar en Go with MySQL es una experiencia encantadora: nunca tuve un problema, mis servidores funcionan durante meses sin errores ni fugas. El hecho de que la mayoría de las funciones simplemente toman un número variable de argumentos aligera una tarea que es tediosa en muchos idiomas.

Tenga en cuenta que si, en el futuro, necesita usar otro controlador MySQL, solo tendrá que cambiar dos líneas en un solo archivo: la línea que realiza la importación y la línea que abre la conexión.

Denys Séguret
fuente
2
Muchas gracias, lo intentaré. Me encanta que Go proporcione el paquete de base de datos / sql que las bibliotecas pueden implementar.
Sergi Mansilla
9
Excelente imprimación para novatos. Gracias.
Rick-777
55
Hay una lista de controladores probados (también para otros DBMS) en code.google.com/p/go-wiki/wiki/SQLDrivers. Hay un segundo controlador MySQL popular: github.com/Go-SQL-Driver/MySQL (escrito por mí)
Julien Schmidt
1
@JulienSchmidt Edité mi respuesta para hacer referencia a su enlace. Si tiene un enlace a una comparación entre esos dos controladores, sería bienvenido.
Denys Séguret
1
@Zeynel Es solo un ejemplo (tomado de este proyecto personal ). Edité reemplazándolo con SomeThing. El punto de esa línea es mostrar cómo llenar directamente una estructura con el resultado de su consulta sin variables intermedias.
Denys Séguret
2

Algunas cosas a tener en cuenta: seleccione el ejemplo de 1 fila:

row := con.QueryRow("select mdpr, x, y, z from sometable where id=?",id) 
cb := new(SomeThing) 
err := row.Scan(&cb.Mdpr, &cb.X, &cb.Y, &cb.Z)

falta un row.Next()en este ejemplo. necesita llamar al row.Next()para agarrar la primera fila devuelta.

También hay cierta inflexibilidad a la biblioteca que de alguna manera trata de promover el minimalismo de datos. si intenta seleccionar columnas que no sean Escanear, arrojará errores (no solo advertencias)

Badoet
fuente
2
Esto no es exacto: la función QueryRow devuelve * Row. Esta función afirma que la consulta devuelve una sola fila. Query () devuelve (* Filas, error), lo que requiere una llamada a filas.Next ().
Alan LaMielle