在Go语言的实际开发中,将字符串转换为int64是非常常见的操作,尤其是处理用户输入、接口返回值或者配置文件内容时,经常需要把字符串形式的数字转为int64类型参与后续计算。但如果字符串长度较长或者内容不符合预期,直接转换很容易引发程序异常,因此需要掌握安全的转换方法。

直接使用strconv.ParseInt的隐患
Go标准库的strconv包提供了ParseInt函数用于字符串转整数,但如果不做额外处理直接使用,很容易出现问题。比如当字符串表示的数值超过int64的取值范围时,函数会返回错误,但如果忽略错误直接取返回值,就会得到不符合预期的结果。
先看一个不安全的示例:
package main
import (
"fmt"
"strconv"
)
func main() {
// 超过int64最大值的字符串
longStr := "9223372036854775808"
num, _ := strconv.ParseInt(longStr, 10, 64)
// 忽略错误直接打印结果,结果不符合预期
fmt.Println(num)
}
上述代码中,字符串对应的数值是int64的最大值加1,已经超出了int64的表示范围,ParseInt会返回错误,但代码中用下划线忽略了错误,得到的num值是错误的,后续如果参与计算会导致逻辑异常。
安全的转换实现步骤
要实现安全的长字符串转int64,需要遵循以下步骤:
- 首先校验字符串是否为空,避免空字符串导致的无效解析
- 使用
strconv.ParseInt指定进制为10,位数为64,获取返回值和错误 - 严格判断错误是否为空,如果有错误直接返回,不处理返回值
- 如果需要进一步校验数值范围,可以在转换成功后做自定义的范围判断
完整的安全转换函数示例
下面是一个封装好的安全转换函数,处理了常见的异常情况:
package main
import (
"errors"
"fmt"
"strconv"
)
// SafeParseInt64 安全将字符串转为int64
// 入参:str 待转换的字符串,min 允许的最小值,max 允许的最大值
// 返回:转换后的int64值和错误,转换失败返回错误
func SafeParseInt64(str string, min, max int64) (int64, error) {
// 校验空字符串
if str == "" {
return 0, errors.New("输入字符串不能为空")
}
// 调用ParseInt转换,进制10,位数64
num, err := strconv.ParseInt(str, 10, 64)
if err != nil {
// 区分不同的错误类型,方便上层处理
if numErr, ok := err.(*strconv.NumError); ok {
if numErr.Err == strconv.ErrRange {
return 0, errors.New("字符串数值超出int64表示范围")
}
if numErr.Err == strconv.ErrSyntax {
return 0, errors.New("字符串包含非数字字符")
}
}
return 0, fmt.Errorf("转换失败: %v", err)
}
// 校验自定义范围
if num < min || num > max {
return 0, fmt.Errorf("数值不在允许的范围[%d, %d]内", min, max)
}
return num, nil
}
func main() {
// 测试用例1:正常转换
testStr1 := "123456789012345"
if num, err := SafeParseInt64(testStr1, 0, 1e18); err != nil {
fmt.Println("转换失败:", err)
} else {
fmt.Println("转换成功,数值为:", num)
}
// 测试用例2:超出int64范围
testStr2 := "9223372036854775808"
if num, err := SafeParseInt64(testStr2, 0, 1e18); err != nil {
fmt.Println("转换失败:", err)
} else {
fmt.Println("转换成功,数值为:", num)
}
// 测试用例3:包含非数字字符
testStr3 := "123abc"
if num, err := SafeParseInt64(testStr3, 0, 1e18); err != nil {
fmt.Println("转换失败:", err)
} else {
fmt.Println("转换成功,数值为:", num)
}
}
常见错误场景说明
| 错误场景 | 原因 | 处理方式 |
|---|---|---|
| 字符串为空 | strconv.ParseInt对空字符串返回语法错误 | 转换前先校验字符串非空 |
| 字符串包含非数字字符 | 不符合整数字面量规则 | 捕获ErrSyntax错误并提示 |
| 字符串数值超出int64范围 | int64最大值为9223372036854775807,最小值为-9223372036854775808 | 捕获ErrRange错误并提示 |
| 忽略错误直接使用返回值 | 错误时返回值为0或者截断后的错误值 | 必须判断错误后再使用返回值 |
特殊情况处理
如果需要处理的字符串可能包含正负号,strconv.ParseInt本身是支持首字符为+或-的,不需要额外处理。如果字符串带有前导零,比如00123,ParseInt也能正确解析为123,不需要提前去除前导零。
如果业务场景中需要支持其他进制(比如16进制、8进制)的字符串转int64,只需要修改ParseInt的第二个参数即可,比如进制为16时,可以解析ff这样的字符串为255。但需要注意,非10进制的字符串转换时,同样要处理溢出和语法错误的问题。
注意:不要使用strconv.Atoi来转int64,因为Atoi返回的是int类型,在不同平台上int的位数可能不同,无法保证是64位,所以转换int64时优先使用ParseInt并指定位数为64。