Qual é a maneira recomendada de se conectar ao MySQL a partir do Go?

163

Estou procurando uma solução confiável para conectar-se a um banco de dados MySQL da Go. Eu já vi algumas bibliotecas por aí, mas é difícil determinar os diferentes estados de integridade e manutenção atual. Não tenho necessidades complicadas, mas gostaria de saber em que as pessoas confiam ou qual é a solução mais padrão para se conectar ao MySQL.

Sergi Mansilla
fonte

Respostas:

263

Alguns drivers estão disponíveis, mas você deve considerar apenas aqueles que implementam a API do banco de dados / sql como

  • fornece uma sintaxe limpa e eficiente,
  • garante que você poderá alterar posteriormente o driver sem alterar seu código, além da importação e conexão.

Dois drivers rápidos e confiáveis ​​estão disponíveis para o MySQL:

Eu usei os dois na produção, os programas estão em execução há meses com números de conexão na casa dos milhões sem falhas.

Outros drivers de banco de dados SQL estão listados no go-wiki .

Importe ao usar o MyMySQL:

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

Importe ao usar o driver Go-MySQL:

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

Conectando e fechando usando o 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

Conectando e fechando usando o Go-MySQL-Driver:

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

Selecione uma linha:

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)

Selecione várias linhas e construa uma matriz com 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})
}

Inserir:

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

Você verá que trabalhar no Go with MySQL é uma experiência agradável: nunca tive um problema, meus servidores funcionam por meses sem erros ou vazamentos. O fato de a maioria das funções simplesmente aceitar um número variável de argumentos facilita uma tarefa que é entediante em muitas línguas.

Observe que se, no futuro, você precisar usar outro driver MySQL, precisará alterar duas linhas em um arquivo go: a linha que faz a importação e a linha que abre a conexão.

Denys Séguret
fonte
2
Muito obrigado, vou tentar. Eu amo que o Go forneça o pacote de banco de dados / sql que as bibliotecas podem implementar.
Sergi Mansilla
9
Excelente cartilha para iniciantes. Obrigado.
Rick-777
5
Uma lista de drivers testados (também para outros DBMSs) está disponível em code.google.com/p/go-wiki/wiki/SQLDrivers Há um segundo driver MySQL popular: github.com/Go-SQL-Driver/MySQL (escrito por mim)
Julien Schmidt
1
@JulienSchmidt Editei minha resposta para referenciar seu link. Se você tiver um link para uma comparação entre esses dois drivers, será bem-vindo.
Denys Séguret
1
@ Zeynel É apenas um exemplo (tirado deste projeto pessoal ). Eu editei substituindo-o por SomeThing. O objetivo dessa linha é mostrar como preencher diretamente uma estrutura com o resultado da sua consulta sem variáveis ​​intermediárias.
Denys Séguret
2

algumas coisas a serem observadas no exemplo de seleção de 1 linha:

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)

está faltando row.Next()neste exemplo. ele precisa chamar o row.Next()para pegar a primeira linha retornada.

também há alguma inflexibilidade na biblioteca que, de alguma forma, tenta promover o minimalismo dos dados. se você tentar selecionar colunas que não são de varredura, gerará erros (não apenas avisos)

Badoet
fonte
2
Isso não é exato: a função QueryRow retorna * Row. Esta função afirma que a consulta retorna uma única linha. Query () retorna (* Linhas, erro), o que requer uma chamada para linhas.Próximo ().
Alan LaMielle