我不确定这是Go中的错误还是我不理解的错误。我有以下内容:
package main
import (
"database/sql"
"log"
"reflect"
_ "github.com/lib/pq"
)
func main() {
Db, err := sql.Open("postgres", "user=yoitsme password=openupitsme host=x.x.x.x dbname=mydb")
if err != nil {
log.Println(err)
}
rows, err := Db.Query("SELECT 1.3250::numeric, 8.548::decimal, 908.234::float, 1234::integer")
defer rows.Close()
for rows.Next() {
var col1, col2, col3, col4 interface{}
if err := rows.Scan(&col1, &col2, &col3, &col4); err != nil {
log.Println(err)
}
log.Println(col1, reflect.TypeOf(col1))
log.Println(col2, reflect.TypeOf(col2))
log.Println(col3, reflect.TypeOf(col3))
log.Println(col4, reflect.TypeOf(col4))
}
if err = rows.Err(); err != nil {
log.Println(err)
}
}
这打印:
2015/08/11 09:35:47 [49 46 51 50 53 48] []uint8
2015/08/11 09:35:47 [56 46 53 52 56] []uint8
2015/08/11 09:35:47 908.234 float64
2015/08/11 09:35:47 1234 int64
所以,我得到[] uint8(例如一个字符串)作为实际数字的前两列。最后两列是预期的。根据Postgresql Numeric & Decimal types are part of the SQL standard。那么,为什么Go不遵循他们的数据库/ sql包中的SQL标准呢?是因为Go没有内置的“Decimal”类型吗?由于语言的缺点,数据库/ sql包将数字转换为字符串似乎是错误的....
因为没有更好的解决方案。 (至少直到Go 1.5's big.Float
)。有什么其他选择吗?
float64
。这是邪恶的。特别是如果你正在使用钱(numeric
和decimal
等类型的用途最多)。这个特定的数据库驱动程序选择返回一个包含数字的字符串 - 让你决定是否失去一些精度(通过float64
将其转换为strconv
)或使用小数/精确数字库(如gmp
或math/big
)。
以下是开发人员对问题的回答:https://github.com/lib/pq/issues/648
将float64类型用于十进制是不安全的,因为浮点数不能表示所有小数。例如,小数点支持的指数远大于浮点数,浮点数系数在转换为基数2表示时会发生变化。将字符串转换为float是很简单的,所以我们将保持这种行为。