使用github.com/jmoiron/sqlx扫描SQL返回值到结构体报错求助
解决sqlx插入后扫描返回值到结构体的问题
问题分析
你的代码存在两个关键问题导致报错:
- 参数传递方式错误:
QueryRowx不支持直接传入结构体作为命名参数,必须使用sqlx提供的命名参数处理方法,否则会触发结构体类型不支持的错误。 - RETURNING子句格式错误:SQL中
RETURNING (first_name, last_name)的写法会让PostgreSQL返回一个复合行类型,而非独立的列,导致StructScan无法正确映射到结构体字段。
修正后的代码
方法1:使用NamedQuery(推荐,更简洁)
package main import ( "log" "github.com/jmoiron/sqlx" _ "github.com/lib/pq" ) const CreateUserSQL = `INSERT INTO users ( first_name, last_name ) VALUES ( :first_name, :last_name ) RETURNING first_name, last_name ` type User struct { FirstName string `db:"first_name"` LastName string `db:"last_name"` } func main() { db, err := sqlx.Connect("postgres", "postgres://postgres:postgres@localhost:5432/postgres?sslmode=disable") if err != nil { log.Fatal(err) } defer db.Close() user := &User{ FirstName: "John", LastName: "Doe", } // 使用NamedQuery处理命名参数 rows, err := db.NamedQuery(CreateUserSQL, user) if err != nil { log.Fatal(err) } defer rows.Close() // 读取返回的行并扫描到结构体 if rows.Next() { err = rows.StructScan(user) if err != nil { log.Fatal(err) } } log.Printf("插入并返回的用户:%+v", user) }
方法2:手动解析命名参数再执行
package main import ( "log" "github.com/jmoiron/sqlx" _ "github.com/lib/pq" ) const CreateUserSQL = `INSERT INTO users ( first_name, last_name ) VALUES ( :first_name, :last_name ) RETURNING first_name, last_name ` type User struct { FirstName string `db:"first_name"` LastName string `db:"last_name"` } func main() { db, err := sqlx.Connect("postgres", "postgres://postgres:postgres@localhost:5432/postgres?sslmode=disable") if err != nil { log.Fatal(err) } defer db.Close() user := &User{ FirstName: "John", LastName: "Doe", } // 将结构体解析为命名参数映射 query, args, err := sqlx.Named(CreateUserSQL, user) if err != nil { log.Fatal(err) } // 把命名参数转换为PostgreSQL支持的$1、$2格式 query = db.Rebind(sqlx.DOLLAR, query) // 执行查询并扫描结果 err = db.QueryRowx(query, args...).StructScan(user) if err != nil { log.Fatal(err) } log.Printf("插入并返回的用户:%+v", user) }
关键修正点说明
- 修正RETURNING子句:去掉列名外的括号,让PostgreSQL返回独立的列,确保
StructScan能通过结构体的db标签匹配字段。 - 使用命名参数处理方法:
NamedQuery是sqlx专门用于处理命名参数查询的方法,直接接收结构体作为参数,自动解析映射到SQL中的:xxx占位符。- 手动解析方式通过
sqlx.Named将结构体转为参数列表,再用db.Rebind适配PostgreSQL的参数格式,适合需要自定义SQL处理的场景。
内容的提问来源于stack exchange,提问作者dmbibishkin
相关产品推荐
相关产品推荐

