Todos os produtos
Search
Central de documentação

Lindorm:Desenvolva aplicações com Go

Última atualização: Jun 28, 2026

Utilize o pacote database/sql do Go com instruções SQL do LindormTable para se conectar ao LindormTable e executar operações CRUD. Este guia aborda:

  • Adição da dependência do Go MySQL Driver

  • Configuração dos parâmetros de conexão e do pool de conexões

  • Criação de tabela, escrita, consulta e exclusão de dados

  • Execução da aplicação de exemplo completa e verificação dos resultados

Pré-requisitos

Antes de começar, certifique-se de ter:

Notas sobre conexão e confiabilidade

  • Os nós de frontend SQL do LindormTable utilizam o Server Load Balancer (SLB) para distribuir requisições de clientes entre os nós. Para manter uma distribuição equilibrada das conexões, evite tempos longos de keep-alive. Configure SetConnMaxLifetime para renovar as conexões periodicamente.

  • Em ambientes de rede complexos — com alta latência, perda de pacotes ou instabilidade — as conexões podem ser interrompidas. Configure um pool de conexões adequado e adicione lógica de nova tentativa no código da sua aplicação.

  • Durante reinicializações do servidor para atualizações, as conexões podem cair temporariamente. Mesmo com um pool de conexões, sua aplicação pode encontrar exceções. Capture esses erros e tente novamente.

  • Ajuste as configurações do pool de conexões de acordo com seu tráfego. Poucas conexões causam enfileiramento de requisições e aumentam o tempo de resposta (RT). Imprima o status do pool para diagnosticar problemas de conexão:

    fmt.Printf("%+v\n", db.Stats())

Conecte-se ao LindormTable

Etapa 1: Adicione a dependência do driver

No arquivo go.mod do seu projeto, adicione o Go MySQL Driver:

require github.com/go-sql-driver/mysql v1.7.1

Etapa 2: Configure os parâmetros de conexão

Defina as constantes de conexão:

const (
    user           = "<your-username>"
    password       = "<your-password>"
    host           = "<LindormTable-endpoint-for-MySQL>"
    port           = 33060
    database       = "default"
    connectTimeout = "10s"
)

Referência de parâmetros

Parâmetro

Descrição

user

Nome de usuário para acesso ao LindormTable. Para redefinir a senha, consulte Manage users.

password

Senha para acesso ao LindormTable.

host

LindormTable Endpoint For MySQL. Consulte View endpoints. Para aplicações implantadas em ECS, use o endpoint de VPC para menor latência e maior segurança. Para acesso via internet, ative o endpoint público no console: Database Connections > Wide Table Engine > Enable Public Endpoint.

port

Valor fixo: 33060.

database

Nome do banco de dados. O padrão é default.

connectTimeout

Tempo limite de conexão. Unidade: segundos (s).

Etapa 3: Abra uma conexão e configure o pool

Construa a URL de conexão e defina as configurações do pool antes de executar qualquer consulta:

url := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?timeout=%s",
    user, password, host, port, database, connectTimeout)

db, err := sql.Open("mysql", url)
if err != nil {
    panic(err.Error())
}
defer db.Close()

// Maximum number of open connections. Default: 0 (unlimited).
// Set this to avoid waiting when connections are exhausted.
db.SetMaxOpenConns(20)

// Maximum number of idle connections. Default: 2.
// Set equal to SetMaxOpenConns to avoid unnecessary connection churn.
db.SetMaxIdleConns(20)

// Maximum idle time before a connection is closed. Default: 0 (no limit).
// 8 minutes is a safe default to reclaim stale idle connections.
db.SetConnMaxIdleTime(8 * time.Minute)

// Maximum connection lifetime. Rotate connections to avoid imbalance
// caused by long-lived persistent connections. 30 minutes recommended.
db.SetConnMaxLifetime(30 * time.Minute)

Trechos de código de exemplo

Todos os exemplos utilizam db.Exec, db.Query e db.Prepare do pacote padrão database/sql do Go.

Liste bancos de dados

rows, err := db.Query("show databases")
if err != nil {
    panic(err.Error())
}
defer rows.Close()

for rows.Next() {
    var dbName string
    if err := rows.Scan(&dbName); err != nil {
        panic(err.Error())
    }
    fmt.Println(dbName)
}

Crie uma tabela

_, err := db.Exec("create table if not exists user_test(id int, name varchar,age int, primary key(id))")
if err != nil {
    fmt.Println("create table error", err)
    return
}

Escreva dados

Escrita direta

_, err = db.Exec("upsert into user_test(id,name,age) values(1,'zhangsan',17)")
if err != nil {
    fmt.Println("insert data error", err)
    return
}

Escrita parametrizada (recomendada para escritas repetidas — reutilize Stmt em cenários de alto throughput)

stmt, err := db.Prepare("upsert into user_test(id,name,age) values(?,?,?)")
if err != nil {
    fmt.Println("prepare error", err)
    return
}
defer stmt.Close()

_, err = stmt.Exec(2, "lisi", 18)
if err != nil {
    fmt.Println("upsert error", err)
    return
}

Consulte dados

Consulta direta

rows, err := db.Query("select * from user_test")
if err != nil {
    fmt.Println("query data error", err)
    return
}
defer rows.Close()

var id int
var name string
var age int
for rows.Next() {
    if err = rows.Scan(&id, &name, &age); err != nil {
        fmt.Println("scan data error", err)
        return
    }
    fmt.Println("id:", id, "name:", name, "age:", age)
}

Consulta parametrizada

stmt, err := db.Prepare("select * from user_test where id=?")
if err != nil {
    fmt.Println("prepare error", err)
    return
}
defer stmt.Close()

rows, err := stmt.Query(1)
if err != nil {
    fmt.Println("query data error", err)
    return
}
defer rows.Close()

var id int
var name string
var age int
for rows.Next() {
    if err = rows.Scan(&id, &name, &age); err != nil {
        fmt.Println("scan data error", err)
        return
    }
    fmt.Println("id:", id, "name:", name, "age:", age)
}

Exclua dados

_, err = db.Exec("delete from user_test where id=1")
if err != nil {
    fmt.Println("delete data error", err)
    return
}

Código de exemplo completo

A seguir, apresentamos um exemplo executável de ponta a ponta que se conecta ao LindormTable, cria uma tabela, escreve linhas, consulta-as e exclui uma delas.

Em produção, carregue credenciais a partir de variáveis de ambiente em vez de codificá-las diretamente no código-fonte.
package main

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

const (
    // Set user to the username used to access LindormTable
    user = "user"
    // Set password to the password used to access LindormTable
    password = "test"
    // Set host to the LindormTable endpoint for MySQL
    host = "ld-uf6k8yqb741t3****-proxy-sql-lindorm-public.lindorm.rds.aliyuncs.com"
    // Port is fixed to 33060
    port = 33060
    // Set database to the name of the database to connect to
    database = "default"
    // Connection timeout
    connectTimeout = "20s"
)

func main() {
    // Build the connection URL and open the connection
    url := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?timeout=%s",
        user, password, host, port, database, connectTimeout)
    db, err := sql.Open("mysql", url)
    if err != nil {
        panic(err.Error())
    }
    defer db.Close()

    // Configure connection pool
    db.SetMaxOpenConns(20)
    db.SetMaxIdleConns(20)
    db.SetConnMaxIdleTime(8 * time.Minute)
    db.SetConnMaxLifetime(30 * time.Minute)

    // Print pool status every 10 seconds for diagnostics
    go func() {
        for {
            fmt.Printf("%+v\n", db.Stats())
            time.Sleep(10 * time.Second)
        }
    }()

    // List databases
    {
        rows, err := db.Query("show databases")
        if err != nil {
            panic(err.Error())
        }
        defer rows.Close()
        for rows.Next() {
            var dbName string
            if err := rows.Scan(&dbName); err != nil {
                panic(err.Error())
            }
            fmt.Println(dbName)
        }
    }

    // Create a table
    {
        _, err := db.Exec("create table if not exists user_test(id int, name varchar,age int, primary key(id))")
        if err != nil {
            fmt.Println("create table error ", err)
            return
        }
    }

    // Write data — method 1: direct write
    {
        _, err = db.Exec("upsert into user_test(id,name,age) values(1,'zhangsan',17)")
        if err != nil {
            fmt.Println("insert data error", err)
            return
        }
    }

    // Write data — method 2: parameterized write
    {
        stmt, err := db.Prepare("upsert into user_test(id,name,age) values(?,?,?)")
        if err != nil {
            fmt.Println("prepare error", err)
            return
        }
        defer stmt.Close()
        _, err = stmt.Exec(2, "lisi", 18)
        if err != nil {
            fmt.Println("upsert error", err)
            return
        }
    }

    // Query data — method 1: direct query
    {
        rows, err := db.Query("select * from user_test")
        if err != nil {
            fmt.Println("query data error", err)
            return
        }
        defer rows.Close()
        var id int
        var name string
        var age int
        for rows.Next() {
            if err = rows.Scan(&id, &name, &age); err != nil {
                fmt.Println("scan data error", err)
                return
            }
            fmt.Println("id:", id, "name:", name, "age:", age)
        }
    }

    // Query data — method 2: parameterized query
    {
        stmt, err := db.Prepare("select * from user_test where id=?")
        if err != nil {
            fmt.Println("prepare error", err)
            return
        }
        defer stmt.Close()
        rows, err := stmt.Query(1)
        if err != nil {
            fmt.Println("query data error", err)
            return
        }
        defer rows.Close()
        var id int
        var name string
        var age int
        for rows.Next() {
            if err = rows.Scan(&id, &name, &age); err != nil {
                fmt.Println("scan data error", err)
                return
            }
            fmt.Println("id:", id, "name:", name, "age:", age)
        }
    }

    // Delete data
    {
        _, err = db.Exec("delete from user_test where id=1")
        if err != nil {
            fmt.Println("delete data error", err)
            return
        }
    }
}
Sempre chame rows.Close() após iterar sobre os resultados. Para cenários de alto throughput, reutilize objetos Stmt . Ao usar APIs com suporte a contexto, como QueryContext e ExecContext , evite tempos limite muito curtos — pausas na coleta de lixo (GC) do cliente podem acionar timeouts de contexto e causar redefinições de conexão.

Verifique os resultados

Quando a instância contém apenas o banco de dados default, a saída é:

default
information_schema
id: 1 name: zhangsan age: 17
id: 2 name: lisi age: 18
id: 1 name: zhangsan age: 17

Essa saída confirma:

  • default e information_schema — existem dois bancos de dados na instância.

  • id: 1 name: zhangsan age: 17 e id: 2 name: lisi age: 18 — ambas as linhas foram escritas com sucesso.

  • id: 1 name: zhangsan age: 17 — a consulta parametrizada (where id=?) retornou a linha com id=1.

Próximos passos