学習備忘ログ

よく使うコードや設定のメモ

【Golang + Sqlx】リレーション先も含めて構造体へのbindを一度でする方法

前提

  • groupテーブルとcategoryテーブルがあり、groupテーブルにcategoryを参照する外部キーが存在してる。

  • 構造体定義

package model


type Group struct {
    ID              int       `json:"id" db:"id"`
    Name            string    `json:"name" db:"name"`
    GroupCategoryId uint64    `json:"groupCategoryId,omitempty"`
    CompanyName     string    `json:"companyName,omitempty" db:"company_name"`
    CompanyId       int       `json:"companyId,omitempty" db:"company_id"`
    Category        *Category `json:"category" db:"category"`
    CategoryId      int       `json:"categoryId,omitempty" db:"category_id"`
}

type Category struct {
    Id    int    `json:"id,omitempty" db:"id"`
    Name  string `json:"name,omitempty" db:"name"`
    Color string `json:"color,omitempty" db:"color"`
}

方法

  • 以下のようにリレーション先の構造体を gc.name as "category.name", gc.color as "category.color"のようにするとbindできる。
func (g *Group) GetGroups(pageSize int, page int) (groups []*model.Group, totalStore, lastPage int, err error) {
    logger.Info("GetGroups persistence")
    stmt, err := g.db.Preparex(`
  SELECT 
  g.id, g.name, c.name as company_name, gc.name as "category.name", gc.color as "category.color", s.total_store, g.created_at
  FROM
      groups AS g
              //省略
  LIMIT ? OFFSET ?
    `)
    if err != nil {
        return nil, 0, 0, err
    }

    const userId = 445
    rows, err := stmt.Queryx(userId, pageSize, pageSize*(page-1))
    if err != nil {
        return nil, 0, 0, err
    }
    defer rows.Close()

    groups = []*model.Group{}
    for rows.Next() {
        var group model.Group
        if err := rows.StructScan(&group); err != nil {
            return nil, 0, 0, err
        }

        groups = append(groups, &group)
    }


    return groups, totalCount, lastPage, nil
}