如何将含数组字段的PostgreSQL行直接映射为Go结构体?
解决方案:直接映射包含PostgreSQL数组的Go结构体
当然可以实现直接映射!问题的核心是原生的[]string类型并没有实现Go数据库驱动要求的sql.Scanner和driver.Valuer接口,所以像sqlx这类ORM工具不知道如何把PostgreSQL的数组值转换为Go切片。下面提供两种简单的解决方法:
方法一:使用pq库提供的数组类型
github.com/lib/pq库已经为PostgreSQL的数组类型封装好了对应的Go类型,比如pq.StringArray,它已经实现了必要的接口,可以直接被数据库工具自动映射。
修改你的结构体:
import "github.com/lib/pq" type Foo struct { Name string `db:"name"` Types pq.StringArray `db:"types"` // 替换[]string为pq.StringArray Role string `db:"role"` }
然后直接使用Select方法:
var foo []Foo // 注意:你的SQL语句里字段名写错了,表结构里是role,不是roles query := `SELECT name, types, role FROM foo` err = dbConn.Select(&foo, query) if err != nil { // 处理错误逻辑 }
这样修改后,sqlx就能自动把PostgreSQL的varchar[]类型映射到结构体的Types字段了。
方法二:自定义类型实现扫描接口
如果你不想替换原生的[]string类型,可以自定义一个类型,让它实现sql.Scanner和driver.Valuer接口,内部复用pq.Array的逻辑:
定义自定义类型:
import ( "database/sql/driver" "github.com/lib/pq" ) type StringArray []string // 实现sql.Scanner接口,用于从数据库读取值 func (sa *StringArray) Scan(value interface{}) error { return pq.Array(sa).Scan(value) } // 实现driver.Valuer接口,用于向数据库写入值 func (sa StringArray) Value() (driver.Value, error) { return pq.Array(sa).Value() }
更新结构体:
type Foo struct { Name string `db:"name"` Types StringArray `db:"types"` // 使用自定义类型 Role string `db:"role"` }
之后同样可以直接用dbConn.Select(&foo, query)完成映射,效果和方法一一致。
小提醒
你的原始SQL语句里写的是SELECT name, types, roles FROM foo,但数据库表的字段是role(单数),这里一定要修正字段名,否则会出现“column does not exist”的错误。
内容的提问来源于stack exchange,提问作者ShailyAggarwal
相关产品推荐
相关产品推荐

