構造体があるとしましょう:
type User struct {
Name string
Id int
Score int
}
そして、同じスキーマを持つデータベーステーブル。データベース行を構造体に解析する最も簡単な方法は何ですか?以下に回答を追加しましたが、それが最良のものかどうかはわかりません。
これを行う1つの方法があります-Scan
関数ですべての構造体の値を手動で割り当てるだけです。
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
}
}
Goパッケージテストは、多くの場合、物事の実行方法に関する手がかりを提供します。たとえば、from 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)
/* . . . */
}
あなたの質問のために、構造に行を照会すると、次のようなものに変換されます:
var row struct {
age int
name string
}
err = db.QueryRow("SELECT|people|age,name|age=?", 3).Scan(&row.age, &row.name)
それはあなたのソリューションに似ていますが、ソリューションを見つける方法を示すことが重要です。
github.com/jmoiron/sqlx をお勧めします。
READMEから:
sqlxは、goの標準
database/sql
ライブラリで一連の拡張機能を提供するライブラリです。sql.DB
、sql.TX
、sql.Stmt
などのsqlxバージョン。基礎となるインターフェースはすべてそのままであるため、それらのインターフェースは標準インターフェースのスーパーセットです。これにより、データベース/ SQLとsqlxを使用して既存のコードベースを統合するのが比較的簡単になります。主な追加概念は次のとおりです。
- 行を構造体(埋め込み構造体サポート付き)、マップ、およびスライスにマーシャルします。
- 準備済みステートメントを含む名前付きパラメーターのサポート
Get
およびSelect
は、クエリから構造/スライスにすばやく移動します
READMEには、構造体への行のスキャンを示すコードスニペットも含まれています。
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)
}
各列を構造体のフィールドに手動でマップする必要がないことに注意してください。 sqlxには、データベース列への構造体フィールドのデフォルトのマッピングがあり、タグを使用してデータベース列を指定できます(上記のTelephoneCode
構造体のPlace
フィールドに注意してください)。詳細については ドキュメント をご覧ください。
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)
}
github.com/gocraft/dbr
(godoc) を使用して、行を構造体にマップできます。
import (
"github.com/gocraft/dbr"
)
func GetUser(name string) (*User, error) {
var u User
rows, err := db.Query("SELECT * FROM users WHERE name = $1 LIMIT 1", name)
if err != nil {
return nil, err
}
// Load uses reflection to map values into a struct.
n, err := dbr.Load(rows, &u)
if err != nil {
return nil, err
}
if n != 1 {
return nil, NotFound
}
return u, nil
}