Go中float64转int必须显式转换,int()向零截断且不检查溢出;安全做法需先用math.Round等指定舍入,再校验NaN、Inf及int范围,推荐优先使用int64。
float64 转 int 会丢精度,Go 不允许隐式转换
go 明确禁止 float64 到 int 的自动类型转换,编译时直接报错 cannot convert x (type float64) to type int。这不是限制,而是提醒你:浮点数转整数必然涉及舍入策略和溢出风险,必须由你显式决定怎么做。
用 int() 强制转换前,必须先处理舍入和范围
int() 是最简方式,但它直接截断小数部分(向零取整),且不检查溢出。对 1e20 或 -1e20 这类超出 int 表示范围的值,结果是未定义行为(通常为错误的截断值,而非 panic)。
安全做法分两步:
- 先用
math.Round()、math.Floor()或math.Ceil()明确指定舍入逻辑 - 再用
math.IsNaN()和math.IsInf()排除异常值,并用math.MinInt64/math.MaxInt64(或目标平台的int范围)做边界检查
例如,安全四舍五入转 int:
func safeFloat64ToInt(f float64) (int, error) {
if math.IsNaN(f) || math.IsInf(f, 0) {
return 0, fmt.Errorf("cannot convert NaN or Inf to int")
}
r := math.Round(f)
if r math.MaxInt64 {
return 0, fmt.Errorf("float64 value %f out of int range", f)
}
return int(r), nil
}
注意 int 在不同平台宽度不同,优先考虑 int64
Go 的 int 类型宽度取决于运行平台(32 位系统是 32 位,64 位系统通常是 64 位),而 float64 始终是 64 位 IEEE 754。这意味着在 32 位系统上,int 最大只能表示约 21 亿,但 float64 可以精确表示远大于此的整数值(如 1e15)。直接转 int 极易溢出。
如果你需要稳定行为,推荐:
- 用
int64替代int(明确宽度,且能容纳全部可精确表示的float64整数) - 或使用
strconv.FormatFloat()+strconv.ParseInt()组合,它会在解析失败时返回 error,天然具备溢出检查
别忽略负数的舍入差异
int(-2.7) 得到 -2(截断),math.Floor(-2.7) 得到 -3,math.Round(-2.7) 得到 -3。很多业务逻辑(比如分页偏移、索引计算)对负数的处理很敏感。不加判断直接用 int() 容易引入边界 bug,尤其是当输入可能来自用户或外部 API 时。
一个典型陷阱是:int(x / y) 在 x 和 y 异号时,结果与数学除法向下取整不一致。这时候应该先用 math.Trunc() 或 math.Floor() 显式控制,再转整型。
真正麻烦的不是怎么写那行转换,而是想清楚:这个浮点数从哪里来?它是否本该是整数?有没有更上游的方式避免浮点参与整数运算?











