Tous les produits
Search
Centre de documentation

Lindorm:Développer des applications avec Go

Dernière mise à jour :Aug 11, 2026

Utilisez le package database/sql de Go conjointement avec les instructions SQL LindormTable pour vous connecter à LindormTable et effectuer des opérations CRUD. Ce guide détaille les étapes suivantes :

  • Ajouter la dépendance du pilote MySQL pour Go

  • Configurer les paramètres de connexion et le pool de connexions

  • Créer une table, écrire, interroger et supprimer des données

  • Exécuter l'exemple d'application complet et vérifier les résultats

Prérequis

Avant de commencer, assurez-vous de disposer des éléments suivants :

Notes sur la connexion et la fiabilité

  • Les nœuds frontaux SQL de LindormTable utilisent Server Load Balancer (SLB) pour répartir les requêtes des clients entre les nœuds frontaux. Pour maintenir une répartition équilibrée des connexions, évitez les temps de maintien de connexion trop longs. Configurez SetConnMaxLifetime afin d'actualiser périodiquement les connexions.

  • Dans des environnements réseau complexes (latence élevée, perte de paquets ou gigue réseau), les connexions peuvent être interrompues. Configurez un pool de connexions approprié et implémentez une logique de nouvelle tentative dans le code de votre application.

  • Lorsque le serveur redémarre pendant les mises à niveau, les connexions peuvent être temporairement perdues. Même avec un pool de connexions, votre application peut rencontrer des exceptions. Interceptez ces erreurs et effectuez une nouvelle tentative.

  • Ajustez les paramètres du pool de connexions en fonction de votre trafic. Un nombre insuffisant de connexions entraîne la mise en file d'attente des requêtes et augmente le temps de réponse (RT). Affichez l'état du pool pour diagnostiquer les problèmes de connexion :

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

Se connecter à LindormTable

Étape 1 : Ajouter la dépendance du pilote

Dans le fichier go.mod de votre projet, ajoutez le pilote MySQL pour Go :

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

Étape 2 : Configurer les paramètres de connexion

Définissez vos constantes de connexion :

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

Référence des paramètres

Paramètre Description
user Nom d'utilisateur pour l'accès à LindormTable. Pour réinitialiser le mot de passe, consultez la rubrique Gérer les utilisateurs.
password Mot de passe pour l'accès à LindormTable.
host LindormTable Endpoint For MySQL. Consultez la rubrique Afficher les endpoints. Pour les applications déployées sur ECS, utilisez l'endpoint VPC pour une latence plus faible et une sécurité accrue. Pour un accès Internet, activez l'endpoint public dans la console : Database Connections > Wide Table Engine > Enable Public Endpoint.
port Valeur fixe : 33060.
database Nom de la base de données. La valeur par défaut est default.
connectTimeout Délai d'expiration de la connexion. Unité : secondes (s).

Étape 3 : Ouvrir une connexion et configurer le pool

Construisez l'URL de connexion et configurez les paramètres du pool avant d'exécuter toute requête :

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)

Exemples de code

Tous les exemples utilisent db.Exec, db.Query et db.Prepare du package standard database/sql de Go.

Lister les bases de données

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

Créer une 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
}

Écrire des données

Écriture directe

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

Écriture paramétrée (recommandée pour les écritures répétées — réutilisez Stmt pour les scénarios à haut débit)

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
}

Interroger des données

Requête directe

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

Requête paramétrée

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

Supprimer des données

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

Exemple de code complet

Voici un exemple exécutable de bout en bout qui se connecte à LindormTable, crée une table, écrit des lignes, les interroge et en supprime une.

En production, chargez les identifiants à partir de variables d'environnement au lieu de les coder en dur dans le code source.
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
        }
    }
}
Appelez toujours rows.Close() après avoir itéré sur les résultats. Pour les scénarios à haut débit, réutilisez les objets Stmt . Lors de l'utilisation d'API sensibles au contexte telles que QueryContext et ExecContext , évitez les délais d'expiration très courts ; les pauses du garbage collection (GC) côté client peuvent déclencher des délais d'expiration du contexte et provoquer des réinitialisations de connexion.

Vérifier les résultats

Lorsque l'instance ne contient que la base de données default, la sortie est la suivante :

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

Cette sortie confirme que :

  • default et information_schema — deux bases de données existent sur l'instance.

  • id: 1 name: zhangsan age: 17 et id: 2 name: lisi age: 18 — les deux lignes ont été écrites avec succès.

  • id: 1 name: zhangsan age: 17 — la requête paramétrée (where id=?) a renvoyé la ligne avec id=1.

Étapes suivantes