gostructpsqlpgx

How to scan a QueryRow into a struct with pgx


We are using a user struct with alot of fields as follow :

type user struct {
    ID       int    `json:"id,omitempty"`
    UUID     string `json:"uuid,omitempty"`
    Role     int    `json:"role,omitempty"`
    Name     string `json:"name,omitempty"`
    Surname  string `json:"surname,omitempty"`
    Phone    string `json:"phone,omitempty"`
    Email    string `json:"email,omitempty"`
    Street   string `json:"street,omitempty"`
    City     string `json:"city,omitempty"`
    Password string `json:"password,omitempty"`
}

And a function to get a user by its email :

func getUserByEmail(email string) (u user, err error) {
    row := db.Psql.QueryRow(
        context.Background(),
        "SELECT * FROM users WHERE email=$1",
        email)
    err = row.Scan(&u.ID, &u.UUID, &u.Role, &u.Name, &u.Surname, &u.Phone, &u.Email, &u.Street, &u.City, &u.Password)
    if err != nil {
        log.Fatal(err)
    }
    return
}

Is there a way to scan directly to a struct rather than all of its property ? Ideally :

row.Scan(&u)

Solution

  • Since version 5.1.0 PGX supports struct scanning.

    type product struct {
        ID    int32
        Name  string
        Price int32
    }
    
    rows, _ := conn.Query(ctx, "select * from products")
    products, err := pgx.CollectRows(rows, pgx.RowToStructByName[product])
    if err != nil {
        fmt.Printf("CollectRows error: %v", err)
        return
    }
    
    for _, p := range products {
        fmt.Printf("%s: $%d\n", p.Name, p.Price)
    }
    

    You can name the fields using db-tags:

    type Name struct {
        Last  string `db:"last_name"`
        First string `db:"first_name"`
    }
    

    Docs: https://pkg.go.dev/github.com/jackc/pgx/v5#RowToStructByName