Go语言,使用sqlx.StructScan扫描嵌入的结构体 [英] Go language, scanning embeded struct with sqlx.StructScan
问题描述
我刚开始学习Go语言。
我写了以下简单的程序。
这里我试图填充所有书籍和相关的Authers结构。
书
struct已嵌入 p>
package main
import(
fmt
log
time
github.com/jmoiron/sqlx
_github.com/lib/pq
)
类型Book struct {
ID int
标题字符串
年份int
Bauther Auther`db:auther`
}
类型Auther struct {
ID int
名字字符串
Dob time.Time
}
func main(){
db,err:= sqlx.Open(postgres,host = localhost user = testuser dbname = testdb password = testuser)
如果err!= nil {
log.Fatal(DB Conn error:,err)
}
b $ b if err = db.Ping(); err!= nil {
log.Fatal(DB Ping error:,err)
}
defer db.Close()
rows,err: db.Queryx(Select b。*,a.name from books b left outer join authers on a.ID = b.auther;)
如果err!= nil {
log.Fatal DB Query error:,err)
}
defer rows.Close()
var books [] * Book
for rows.Next b $ b var b =& Book {}
err:= rows.StructScan(b)
如果err!= nil {
log.Fatal(Scan error:
}
books = append(books,b)
}
//打印所有书籍
for _,b:= range books {
fmt.Printf(%v,b)
}
}
但是当我运行它,它给出以下错误
[samtech @ sam sqlxapp] $ go run main.go
2016/02/11 18:45:46扫描错误:缺少目标名称名称
退出状态1
我做错了什么?
我也试过在 Book
到
Bauther Auther`db:auther,prefix = auth。`
并将查询更改为
rows, = db.Queryx(Select b。*,auth.name from books b left outer join authers auth on auth.ID = b.auther;)
但不会改变。
EDIT
$ b
经过几次尝试和错误,最后我使它工作。
我必须稍微改变我创建的模型。我改变了Book结构从
type Book struct {
ID int
标题字符串
年int
Bauther Auther
}
到
类型Book struct {
ID int // Key
标题字符串
年份int
AutherID int`db: auther`// FKey
Auther
}
工作正常。我做错了,我添加 Bauther
字段为 Auther
。 Sqlx不明白。但是当我添加 Auther
作为匿名嵌入式结构时,问题解决了。
但是它引入了另一个问题: / p>
由于ID字段存在于 Book
以及 Auther
两个结构体。现在ScanStruct正在填充 Book.ID
在所有行中为0.
有什么我可以做,以避免它?
这似乎不可能与sqlx目前。有一个开放的问题: https://github.com/jmoiron/sqlx/issues/131
不过不需要使用sqlx就可以这么做:
package main
import(
database / sql
fmt
log
time
b $ b _github.com/lib/pq
)
类型书架{
ID int
标题字符串
年int $ b Bauther Auther
}
类型Auther struct {
ID int
名称字符串
Dob time.Time
}
func main(){
db,err:= sql.Open(postgres,postgres:// localhost / testdb?sslmode = disable)
如果err!= nil {
log.Fatal(DB Conn error:,err)
}
如果err = db.Ping(); err!= nil {
log.Fatal(DB Ping error:,err)
}
defer db.Close()
rows,err: db.Query(Select b.id,b.title,b.year,a.id,a.name,a.dob from books b left outer join authers a on a.ID = b.auther;)
if err!= nil {
log.Fatal(DB Query error:,err)
}
defer rows.Close()
var books [] * Book
for rows.Next(){
var b =& Book {}
如果err:= rows.Scan(& b.ID,& b.Title ,& b.Year,& b.Bauther.ID,& b.Bauther.Name,& b.Bauther.Dob); err!= nil {
log.Fatal(err)
}
books = append(books,b)
}
//打印所有图书
for _,b:=范围书{
fmt.Printf(%v,b)
}
}
基本上你必须明确你的 SELECT
语句中的列,的人。然后你创建你的结构,并扫描到每个元素,其顺序与你的 SELECT
语句中的列相同。
I have just started learning Go language. I wrote following simple program.
Here i am trying to fill struct with all Books and related Authers.
Book
struct has embeded Author
struct.
package main
import (
"fmt"
"log"
"time"
"github.com/jmoiron/sqlx"
_ "github.com/lib/pq"
)
type Book struct {
ID int
Title string
Year int
Bauther Auther `db:"auther"`
}
type Auther struct {
ID int
Name string
Dob time.Time
}
func main() {
db, err := sqlx.Open("postgres", "host=localhost user=testuser dbname=testdb password=testuser")
if err != nil {
log.Fatal("DB Conn error: ", err)
}
if err = db.Ping(); err != nil {
log.Fatal("DB Ping error: ", err)
}
defer db.Close()
rows, err := db.Queryx("Select b.*, a.name from books b left outer join authers a on a.ID=b.auther;")
if err != nil {
log.Fatal("DB Query error: ", err)
}
defer rows.Close()
var books []*Book
for rows.Next() {
var b = &Book{}
err := rows.StructScan(b)
if err != nil {
log.Fatal("Scan error: ", err)
}
books = append(books, b)
}
// print all books
for _, b := range books {
fmt.Printf("%v", b)
}
}
But when i run it, it is giving following error
[samtech@sam sqlxapp]$ go run main.go
2016/02/11 18:45:46 Scan error: missing destination name name
exit status 1
What i am doing wrong?
I have also tried changing field tag in Book
struct to
Bauther Auther `db:"auther,prefix=auth."`
and change query to
rows, err := db.Queryx("Select b.*, auth.name from books b left outer join authers auth on auth.ID=b.auther;")
But it doesn't make any change.
EDIT
After few try and errors, finally i make it working.
I have to slightly change the Models that i have created. I changed Book struct from
type Book struct {
ID int
Title string
Year int
Bauther Auther
}
to
type Book struct {
ID int // Key
Title string
Year int
AutherID int `db:"auther"` // FKey
Auther
}
Now, it is working fine. The mistake i was doing was, i added Bauther
field as Auther
. Sqlx could not understand it. But when i added Auther
as anonymous embedded struct, the problem resolved.
But it introduces another problem :)
As ID field exist in Book
as well as in Auther
both the structs. Now ScanStruct is filling Book.ID
with 0 in all rows.
Is there anything that i can do to avoid it?
This doesn't seem possible with sqlx at the moment. There is a open issue for this: https://github.com/jmoiron/sqlx/issues/131
You can however do that easily without using sqlx:
package main
import (
"database/sql"
"fmt"
"log"
"time"
_ "github.com/lib/pq"
)
type Book struct {
ID int
Title string
Year int
Bauther Auther
}
type Auther struct {
ID int
Name string
Dob time.Time
}
func main() {
db, err := sql.Open("postgres", "postgres://localhost/testdb?sslmode=disable")
if err != nil {
log.Fatal("DB Conn error: ", err)
}
if err = db.Ping(); err != nil {
log.Fatal("DB Ping error: ", err)
}
defer db.Close()
rows, err := db.Query("Select b.id, b.title, b.year, a.id, a.name, a.dob from books b left outer join authers a on a.ID=b.auther;")
if err != nil {
log.Fatal("DB Query error: ", err)
}
defer rows.Close()
var books []*Book
for rows.Next() {
var b = &Book{}
if err := rows.Scan(&b.ID, &b.Title, &b.Year, &b.Bauther.ID, &b.Bauther.Name, &b.Bauther.Dob); err != nil {
log.Fatal(err)
}
books = append(books, b)
}
// print all books
for _, b := range books {
fmt.Printf("%v", b)
}
}
Basically you have to be explicit of your columns in your SELECT
statement, so that you know the order of them. Then you create your struct and scan into each element with the same order as your columns in your SELECT
statement.
这篇关于Go语言,使用sqlx.StructScan扫描嵌入的结构体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!