98 votes

Comment convertir une ligne de base de données en une structure ?

Disons que j'ai une structure :

type User struct {
    Name  string
    Id    int
    Score int
}

Et une table de base de données avec le même schéma. Quel est le moyen le plus simple d'analyser une ligne de base de données dans une structure ? J'ai ajouté une réponse ci-dessous mais je ne suis pas sûr que ce soit la meilleure.

109voto

peterSO Points 25725

Les tests des paquets Go fournissent souvent des indices sur la façon de faire les choses. Par exemple, de database/sql/sql_test.go ,

func TestQuery(t *testing.T) {
    /* . . . */
    rows, err := db.Query("SELECT|people|age,name|")
    if err != nil {
            t.Fatalf("Query: %v", err)
    }
    type row struct {
            age  int
            name string
    }
    got := []row{}
    for rows.Next() {
            var r row
            err = rows.Scan(&r.age, &r.name)
            if err != nil {
                    t.Fatalf("Scan: %v", err)
            }
            got = append(got, r)
    }
    /* . . . */
}

func TestQueryRow(t *testing.T) {
    /* . . . */
    var name string
    var age int
    var birthday time.Time
    err := db.QueryRow("SELECT|people|age,name|age=?", 3).Scan(&age)
    /* . . . */
}

Ce qui, pour votre question, à savoir l'interrogation d'une ligne dans une structure, se traduirait par quelque chose du genre :

var row struct {
    age  int
    name string
}
err = db.QueryRow("SELECT|people|age,name|age=?", 3).Scan(&row.age, &row.name)

Je sais que cela ressemble à votre solution, mais il est important de montrer comment trouver une solution.

69voto

ckeeney Points 349

Je recommande github.com/jmoiron/sqlx .

Dans le fichier README :

sqlx est une bibliothèque qui fournit un ensemble d'extensions sur le standard de go. database/sql bibliothèque. Les versions sqlx de sql.DB , sql.TX , sql.Stmt et autres laissent tous les interfaces sous-jacentes intactes, de sorte que que leurs interfaces sont un sur-ensemble des interfaces standard. Cela rend relativement facile d'intégrer des bases de code existantes utilisant base de données/sql avec sqlx.

Les principaux concepts supplémentaires sont :

  • Maréchalisez les rangées en structs (avec le support des struct intégrés), maps et slices.
  • Soutien aux paramètres nommés, y compris les déclarations préparées
  • Get y Select pour passer rapidement d'une requête à une structure/une tranche

Le fichier README comprend également un extrait de code démontrant l'analyse d'une ligne dans une structure :

type Place struct {
    Country       string
    City          sql.NullString
    TelephoneCode int `db:"telcode"`
}
// Loop through rows using only one struct
place := Place{}
rows, err := db.Queryx("SELECT * FROM place")
for rows.Next() {
    err := rows.StructScan(&place)
    if err != nil {
        log.Fatalln(err)
    } 
    fmt.Printf("%#v\n", place)
}

Notez que nous n'avons pas eu à faire correspondre manuellement chaque colonne à un champ de la structure. sqlx propose des correspondances par défaut entre les champs de la structure et les colonnes de la base de données, ainsi que la possibilité de spécifier les colonnes de la base de données à l'aide de balises (notez la balise TelephoneCode du champ de la Place structure ci-dessus). Vous pouvez en savoir plus à ce sujet dans la documentation .

43voto

Kevin Burke Points 5819

Voici une façon de procéder : il suffit d'attribuer manuellement toutes les valeurs de la structure dans le fichier Scan fonction.

func getUser(name string) (*User, error) {
    var u User
    // this calls sql.Open, etc.
    db := getConnection()
    // note the below syntax only works for postgres
    err := db.QueryRow("SELECT * FROM users WHERE name = $1", name).Scan(&u.Id, &u.Name, &u.Score)
    if err != nil {
        return &User{}, err
    } else {
        return &u, nil
    }
}

7voto

rows, err := connection.Query("SELECT `id`, `username`, `email` FROM `users`")

if err != nil {
    panic(err.Error())
}

for rows.Next() {
    var user User

    if err := rows.Scan(&user.Id, &user.Username, &user.Email); err != nil {
        log.Println(err.Error())
    }

    users = append(users, user)
}

Exemple complet

1voto

deemok Points 2137

Il y a un paquet juste pour ça : sqlstruct

Malheureusement, la dernière fois que j'ai vérifié, il ne prenait pas en charge les structures intégrées (qu'il est facile d'implémenter soi-même - j'ai eu un prototype fonctionnel en quelques heures).

Je viens de valider les modifications que j'ai apportées à sqlstruct

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X