Golang中SQL查询结果JSON返回时数值被识别为Base64的问题
解决SQL查询数值类型被JSON编码为Base64的问题
这个问题的根源很明确:当你用rows.MapScan(results)时,sqlx对于numeric/float这类非整数数值类型,并没有自动转换成Go的数值类型(比如float64),而是返回了原始的字节数组([]byte)或者sql.RawBytes。而Go标准库的json编码器在处理[]byte类型时,默认会将其编码为Base64字符串,这就是你看到QTY字段变成"OC4wMA=="的原因(解码后其实是8.00)。
下面给你几个可行的解决方案:
方案1:手动转换Map中的字节类型值
在MapScan之后,遍历结果Map,将[]byte类型的数值转换为对应的数值类型:
rows, err := db.Queryx(query) if err != nil { // 处理查询错误 return } defer rows.Close() enc := json.NewEncoder(w) for rows.Next() { results := make(map[string]interface{}) err = rows.MapScan(results) if err != nil { // 处理扫描错误 continue } // 遍历Map,转换[]byte类型的数值 for key, val := range results { if byteVal, ok := val.([]byte); ok { // 尝试转换为float64 floatVal, err := strconv.ParseFloat(string(byteVal), 64) if err == nil { results[key] = floatVal continue } // 如果是整数形式的字节,也可以尝试转int intVal, err := strconv.Atoi(string(byteVal)) if err == nil { results[key] = intVal } } } if err := enc.Encode(results); err != nil { fmt.Fprintf(w,"%s\n", results) } }
如果你的数值是高精度的decimal类型,推荐使用github.com/shopspring/decimal库来避免精度损失:
import "github.com/shopspring/decimal" // ... 其他代码 ... for key, val := range results { if byteVal, ok := val.([]byte); ok { decVal, err := decimal.NewFromString(string(byteVal)) if err == nil { results[key] = decVal } } }
方案2:使用结构体代替Map(推荐)
定义一个与查询结果字段匹配的结构体,明确指定字段类型,然后用rows.StructScan代替MapScan。这种方式更可靠,sqlx会自动帮你完成类型映射:
// 定义结构体,字段名和数据库列名对应(可以用db标签指定) type OrderResult struct { ID int `db:"ID"` QTY float64 `db:"QTY"` // 如果是高精度decimal,用decimal.Decimal类型 // QTY decimal.Decimal `db:"QTY"` } // ... 其他代码 ... rows, err := db.Queryx(query) if err != nil { // 处理错误 return } defer rows.Close() enc := json.NewEncoder(w) for rows.Next() { var res OrderResult err = rows.StructScan(&res) if err != nil { // 处理扫描错误 continue } if err := enc.Encode(res); err != nil { fmt.Fprintf(w,"%s\n", res) } }
这个方案的优势在于类型明确,避免了Map带来的类型不确定性,同时也更符合Go的类型安全原则。
额外提示
- 如果你使用的是PostgreSQL等数据库,确保驱动已经正确配置,有些驱动需要显式设置类型映射才能正确转换numeric类型。
- 对于decimal类型,尽量避免直接用
float64存储,防止精度丢失,使用专门的decimal库是更好的选择。
内容的提问来源于stack exchange,提问作者sibert
相关产品推荐
相关产品推荐

