関連記事
GitHub - devlights/blog-summary: ブログ「いろいろ備忘録日記」のまとめ
概要
以下、自分用のメモです。よく忘れるのでここにメモメモ。。
Goの標準ライブラリを使って、データベースからSELECTした結果を取得する場合に Scan メソッドを使いますが
たまに、マップで欲しいときもあります。ちょっとしたツール作ってて、いちいち構造体切るのが面倒なときとか。
んで、この Scan メソッドさんにはポインタを渡さないと行けないので、必要なカラム分を一気に取得したい場合にどうするの?ってなったりします。
(私は最初なりました)
ちょっと手間ですが、スライスを2つ作って処理することが出来ます。
サンプル
package sqlmap import "database/sql" // MapRows maps the data in the given *sql.Rows to []map[string]any. // // This code is based on the ideas presented at the following URL: // - https://kylewbanks.com/blog/query-result-to-map-in-golang func MapRows(rows *sql.Rows) ([]map[string]any, error) { var ( cols []string err error ) cols, err = rows.Columns() if err != nil { return nil, err } var ( result = make([]map[string]any, 0) ) for rows.Next() { var ( c = make([]any, len(cols)) // column values cp = make([]any, len(cols)) // pointer of column value ) for i := 0; i < len(c); i++ { cp[i] = &c[i] } err = rows.Scan(cp...) if err != nil { return nil, err } var ( m = make(map[string]any) ) for i, name := range cols { v := cp[i].(*any) m[name] = *v } result = append(result, m) } return result, nil }
最初に値を格納するスライスを作って、その後にそのポインタを格納するスライスを用意します。
それを Scan メソッドに ...
付きで渡したら一気に取得できます。
テストコードは以下。
package sqlmap import ( "database/sql" "testing" _ "github.com/glebarez/go-sqlite" ) func TestMapRows(t *testing.T) { // // Arrange // db, err := sql.Open("sqlite", "testdb/chinook.db") if err != nil { t.Error(err) } defer db.Close() rows, err := db.Query("SELECT * FROM artists ORDER BY ArtistId DESC LIMIT 5") if err != nil { t.Error(err) } defer rows.Close() // // Act // m, err := MapRows(rows) // // Assert // if err != nil { t.Error(err) } if m == nil { t.Errorf("[want] not nil\t[got] nil") } for _, v := range m { t.Logf("[row] %v", v) } }
実行すると以下のような結果になります。
$ task test task: [test] go test -v ./... === RUN TestMapRows maprows_test.go:43: [row] map[ArtistId:275 Name:Philip Glass Ensemble] maprows_test.go:43: [row] map[ArtistId:274 Name:Nash Ensemble] maprows_test.go:43: [row] map[ArtistId:273 Name:C. Monteverdi, Nigel Rogers - Chiaroscuro; London Baroque; London Cornett & Sackbu] maprows_test.go:43: [row] map[ArtistId:272 Name:Emerson String Quartet] maprows_test.go:43: [row] map[ArtistId:271 Name:Mela Tenenbaum, Pro Musica Prague & Richard Kapp] --- PASS: TestMapRows (0.00s) PASS ok github.com/devlights/sqlmap
リポジトリ
上のMapRows関数を定義してるライブラリを以下のリポジトリにアップしました。
参考情報
Goのおすすめ書籍
上の書籍の日本語版が下です。
過去の記事については、以下のページからご参照下さい。
サンプルコードは、以下の場所で公開しています。