比方说,我有一个结构:如何在Go中将数据库行转换为结构体?
type User struct {
Name string
Id int
Score int
}
而且具有相同的架构的数据库表。将数据库行解析为结构最简单的方法是什么?我在下面添加了一个答案,但我不确定它是最好的答案。
比方说,我有一个结构:如何在Go中将数据库行转换为结构体?
type User struct {
Name string
Id int
Score int
}
而且具有相同的架构的数据库表。将数据库行解析为结构最简单的方法是什么?我在下面添加了一个答案,但我不确定它是最好的答案。
下面介绍一种方法 - 只需在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
}
}
去包测试通常提供线索的方式做事。例如,从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)
我知道,类似于您的解决方案,但它的重要的是展示如何找到解决方案。
如果简单的方法是手动将列绑定到struct字段我想知道什么是困难的方法 –
不幸的是,这并不是很方便,尤其是在更大的结构的情况下 - 手动绑定结构属性是完全失败的...使用jmoiron/sqlx或其他库更有效率... – shadyyx
我一直没有收回rows.Scan ()。所有的变量都被设置为空。 –
您可以映射行制作成使用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
}
自述:
SQLX是提供随时随地的标准
database/sql
库一组扩展库。 sqlx版本的sql.DB
,sql.TX
,sql.Stmt
,et al。所有的接口都保持不变,所以它们的接口是标准接口的超集。这使得使用 数据库/ sql与sqlx集成现有代码库相对简单。主要补充的概念是:
- 元帅行到结构(具有嵌入式结构的支持),地图,和切片
- 命名参数支持,包括准备好的发言
Get
和Select
从查询赶紧去结构/切片
自述还包括代码片段演示扫描一行到一个结构:
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具有结构字段到数据库列的一些默认映射,以及能够使用标签指定数据库列(注意上面的Place
结构的TelephoneCode
字段)。你可以在the documentation阅读更多。
谢谢你的提示! –
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)
}
怎么会空值的工作? – emostafa
@eslammostafa在什么时候这个代码可以有NULL值的问题? – deFreitas
@deFreitas在比分例如,我的意思是来自数据库的空值。 – emostafa