You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何MySQL指定FLOAT类型却实际存储为DOUBLE?

问题:MySQL FLOAT字段读取后变成DOUBLE精度?

我在MySQL中创建了如下表:

create table testfloat (f float unsigned);
insert into testfloat values (70.99);

预期存储的是70.99的32位FLOAT等值,但用Go代码读取后,得到的却是64位DOUBLE的精度值。

使用的Go读取代码:

package main

import (
    "database/sql"
    "fmt"
    "strconv"

    _ "github.com/go-sql-driver/mysql"
)

func main() {
    db, err := sql.Open("mysql", "root@(localhost)/test")
    if err != nil {
        panic(err)
    }

    rows, err := db.Query("select f from testfloat;")
    if err != nil {
        panic(err)
    }

    fmt.Printf("32-bit 70.99: %s\n", strconv.FormatFloat(70.99, 'f', 50, 32))
    fmt.Printf("64-bit 70.99: %s\n", strconv.FormatFloat(70.99, 'f', 50, 64))
    fmt.Printf("64-bit 70.99 cast from 32-bit 70.99: %s\n", strconv.FormatFloat(float64(float32(70.99)), 'f', 50, 64))

    var f float64
    for rows.Next() {
        if err := rows.Scan(&f); err != nil {
            panic(err)
        }
        fmt.Printf("DB 70.99: %.50f\n", f)
    }
}

输出结果:

32-bit 70.99: 70.98999786376953125000000000000000000000000000000000
64-bit 70.99: 70.98999999999999488409230252727866172790527343750000
64-bit 70.99 cast from 32-bit 70.99: 70.98999786376953125000000000000000000000000000000000
DB 70.99: 70.98999999999999488409230252727866172790527343750000

实际读取的结果和64位DOUBLE的70.99一致,而非32位FLOAT的等值,这是为什么?

原因分析

  • MySQL协议的自动转换:MySQL在通过客户端协议返回FLOAT类型数据时,会自动将32位FLOAT转换为64位DOUBLE发送。这是协议的默认行为,目的是避免传输过程中出现额外精度损失,所以即使表中存的是32位FLOAT,客户端拿到的已经是转换后的DOUBLE值。

  • Go驱动的处理逻辑:go-sql-driver/mysql驱动接收MySQL返回的DOUBLE数据后,直接映射到Go的float64类型,不会逆向转换回32位FLOAT。所以用float64接收时,得到的就是MySQL转换后的DOUBLE精度值。

  • 验证存储类型的方法:如果要确认数据库中确实存的是32位FLOAT,可以在MySQL命令行执行SELECT f, HEX(f) FROM testfloat;,对比十六进制值:32位FLOAT的70.99对应十六进制428B3D71,而DOUBLE对应405279999999999A,就能确认存储类型没问题,只是传输时被转换了。

内容的提问来源于stack exchange,提问作者wingerse

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 06:50:28