Golang中HTML表格数值显示为[53 48 48 46 48 48]的解决方法

Golang中HTML表格数值显示为[53 48 48 46 48 48]的解决方法 数据以“numeric(8,2)”类型存储,在使用PGAdmin的SQL查询中能正确显示为数值。

但在Go中获取相同查询时,数值会被破坏并变成[53 48 48 46 48 48],除非我将数值类型转换为“text”。我使用的是sqlx。

list := get(query)
tpl.ExecuteTemplate(w, "hrlist.html", list)

image

所有文本显示正确。

如何在Go中转换数值?


更多关于Golang中HTML表格数值显示为[53 48 48 46 48 48]的解决方法的实战教程也可以访问 https://www.itying.com/category-94-b0.html

5 回复

在你上面的例子中,list 是什么类型?假设它是一个切片,你可以通过迭代来创建一个新的列表。

更多关于Golang中HTML表格数值显示为[53 48 48 46 48 48]的解决方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


看起来数据是以 []byte 类型返回的,但实际上它是一个 string 类型。

你应该能够将其转换为字符串,这样它就会正确显示。

ncw: 你应该能够将其转换为字符串,这样它就会正确显示。

我该如何使用Go来实现这一点?在SQL中,我必须为数百个字段中的每一个都进行转换。在Go中肯定有更聪明的方法。难道不是吗?

ncw:

你上面例子中的 list 是什么类型?

[map[hr_code:PM hr_date:2020-08-22 hr_id:34 hr_job:20-0001 hr_ppu:[49 48 48 48 46 48 48]]

这是一个典型的数据库驱动类型处理问题。[53 48 48 46 48 48] 是ASCII码值,对应字符串 "500.00"。问题在于PostgreSQL的numeric类型在Go中被解析为了[]byte而不是期望的数值类型。

以下是几种解决方案:

方案1:使用sqlx的StructScan(推荐)

定义结构体时使用*string*float64类型:

type Record struct {
    ID        int      `db:"id"`
    Amount    *string  `db:"amount"`  // 使用指针类型
    // 或者使用float64
    // Amount    *float64 `db:"amount"`
}

func getRecords() ([]Record, error) {
    var records []Record
    query := `SELECT id, amount::text as amount FROM your_table` // 转换为text
    err := db.Select(&records, query)
    return records, err
}

方案2:使用自定义类型扫描

创建自定义类型来处理numeric字段:

type NumericString string

func (n *NumericString) Scan(value interface{}) error {
    switch v := value.(type) {
    case []byte:
        *n = NumericString(v)
    case string:
        *n = NumericString(v)
    default:
        return fmt.Errorf("unsupported type: %T", value)
    }
    return nil
}

type Record struct {
    ID     int           `db:"id"`
    Amount NumericString `db:"amount"`
}

方案3:在查询中直接转换类型

修改SQL查询,将numeric转换为text:

query := `
    SELECT 
        id, 
        amount::text as amount,  -- 在数据库层面转换
        other_fields
    FROM your_table
`

var records []map[string]interface{}
err := db.Select(&records, query)

方案4:使用pgx驱动

如果使用pgx驱动,它提供了更好的PostgreSQL类型支持:

import (
    "github.com/jackc/pgx/v4/pgxpool"
    "github.com/jackc/pgtype"
)

type Record struct {
    ID     int                `db:"id"`
    Amount pgtype.Numeric     `db:"amount"`
    
    // 或者使用自定义方法
    AmountFloat float64       `db:"-"`
}

// 实现自定义扫描
func (r *Record) AfterScan() error {
    var f float64
    if err := r.Amount.AssignTo(&f); err == nil {
        r.AmountFloat = f
    }
    return nil
}

方案5:使用Rows扫描并手动处理

rows, err := db.Queryx(query)
if err != nil {
    return err
}
defer rows.Close()

var results []map[string]interface{}
for rows.Next() {
    row := make(map[string]interface{})
    err := rows.MapScan(row)
    if err != nil {
        return err
    }
    
    // 手动转换numeric字段
    if amountBytes, ok := row["amount"].([]byte); ok {
        row["amount"] = string(amountBytes)
    }
    
    results = append(results, row)
}

完整示例

package main

import (
    "fmt"
    "github.com/jmoiron/sqlx"
    _ "github.com/lib/pq"
)

type Product struct {
    ID     int     `db:"id"`
    Price  string  `db:"price"`  // 使用string接收
    Name   string  `db:"name"`
}

func main() {
    db, err := sqlx.Connect("postgres", "user=postgres dbname=test sslmode=disable")
    if err != nil {
        panic(err)
    }
    defer db.Close()
    
    // 方法1:查询时转换
    query := `SELECT id, price::text as price, name FROM products`
    var products []Product
    err = db.Select(&products, query)
    
    // 方法2:使用临时结构体
    var tempProducts []struct {
        ID    int    `db:"id"`
        Price []byte `db:"price"`
        Name  string `db:"name"`
    }
    
    err = db.Select(&tempProducts, "SELECT * FROM products")
    for i := range tempProducts {
        products = append(products, Product{
            ID:    tempProducts[i].ID,
            Price: string(tempProducts[i].Price), // 转换[]byte为string
            Name:  tempProducts[i].Name,
        })
    }
}

最简洁的解决方案是在SQL查询中使用::text转换,或者在结构体中使用string类型配合适当的扫描处理。

回到顶部