Gorm自定义字符串类型查询时出现Scanner错误求助
解决GORM扫描数据库数组字段到自定义切片类型的错误
问题根源
数据库返回的数组字段以字符串格式(如"{Category1,Category2}")传递,但[]DataCategory未实现sql.Scanner接口,无法完成自动类型转换,导致扫描失败。
解决方案
给自定义切片类型同时实现sql.Scanner(读取数据库值)和driver.Valuer(写入数据库值)接口,完成双向类型转换。
完整代码实现
import ( "database/sql/driver" "fmt" "strings" ) type DataCategory string const ( DataCategory1 DataCategory = "Category1" DataCategory2 DataCategory = "Category2" ) // 定义切片别名,用于实现数据库接口 type DataCategorySlice []DataCategory // 实现driver.Valuer接口:将切片转换为数据库可识别的格式 func (s DataCategorySlice) Value() (driver.Value, error) { if s == nil { return nil, nil } if len(s) == 0 { return "{}", nil } strSlice := make([]string, len(s)) for i, dc := range s { strSlice[i] = string(dc) } return fmt.Sprintf("{%s}", strings.Join(strSlice, ",")), nil } // 实现sql.Scanner接口:将数据库返回的字符串解析为切片 func (s *DataCategorySlice) Scan(src interface{}) error { if src == nil { *s = nil return nil } rawStr, ok := src.(string) if !ok { return fmt.Errorf("expected string type, got %T", src) } // 处理空数组场景 if rawStr == "{}" { *s = DataCategorySlice{} return nil } // 去除首尾大括号并分割元素 trimmedStr := strings.Trim(rawStr, "{}") elements := strings.Split(trimmedStr, ",") // 转换为DataCategorySlice result := make(DataCategorySlice, len(elements)) for i, elem := range elements { result[i] = DataCategory(strings.TrimSpace(elem)) // 处理元素前后可能的空格 } *s = result return nil } // 修改Data结构体的Categories字段类型为实现了接口的DataCategorySlice type Data struct { Name string `json:"name"` Categories DataCategorySlice `json:"category" gorm:"type:text[]"` }
注意事项
- 确保数据库字段类型与GORM tag中的
type:text[]匹配(以PostgreSQL为例,对应text[]数组类型)。 - Scanner逻辑处理了空数组、nil值以及元素前后空格的情况,兼容手动插入数据时的格式差异。
内容的提问来源于stack exchange,提问作者kozhioyrin
相关产品推荐
相关产品推荐

