
本文讲解如何安全地从字符串中提取连续数字字符、转换为整数并计算其乘积,重点解决空指针错误、初始值设置和错误处理逻辑等常见陷阱。
本文讲解如何安全地从字符串中提取连续数字字符、转换为整数并计算其乘积,重点解决空指针错误、初始值设置和错误处理逻辑等常见陷阱。
在 Go 中处理数字字符串时,一个典型需求是:从长数字串中截取指定起始位置的若干连续数字,将其逐个转为整数后求乘积。但初学者常因细节疏忽导致运行时 panic 或结果错误。以下是一个完整、健壮的实现方案。
? 问题分析与修复要点
原代码存在三个关键问题:
- 初始值错误:mult := 0 导致无论后续如何累乘,结果恒为 0(任何数 × 0 = 0);应初始化为 1(乘法单位元)。
- 错误检查逻辑颠倒:if err != nil 后执行 mult *= int(digit) —— 此时 digit 未定义(strconv.Atoi 在失败时返回零值 0 和非 nil 错误),且 err.Error() 在 err == nil 时调用会触发 panic。
- 越界风险未防护:startIndex + i 可能超出字符串长度,需提前校验。
✅ 正确实现(含边界保护)
package main
import (
"fmt"
"strconv"
)
func main() {
inputNum := "73167176531330624919225119"
mult := getMult(3, 10, inputNum) // 从索引3开始,取10位数字
fmt.Printf("Mult = %d\n", mult) // 输出: Mult = 238140
}
// getMult 计算从 startIndex 开始的 length 位数字的乘积
// 返回值为 -1 表示参数非法(越界或非数字字符)
func getMult(startIndex, length int, s string) int {
// 边界检查:防止索引越界
if startIndex < 0 || length <= 0 || startIndex+length > len(s) {
fmt.Printf("Invalid range: startIndex=%d, length=%d, string length=%d\n",
startIndex, length, len(s))
return -1
}
mult := 1
for i := 0; i < length; i++ {
char := s[startIndex+i]
// 快速校验是否为数字字符(避免 strconv 开销)
if char < '0' || char > '9' {
fmt.Printf("Non-digit character '%c' at position %d\n", char, startIndex+i)
return -1
}
digit := int(char - '0') // ASCII 直接转换,高效且无 error
mult *= digit
}
return mult
}? 优化说明
- 避免 strconv.Atoi:对单个 ASCII 数字字符,直接 char - '0' 转换更高效、零开销、永不报错;
- 显式范围校验:在循环前检查 startIndex+length ≤ len(s),杜绝 panic;
- 语义清晰的函数签名:增加 length 参数,使意图明确(原代码硬编码 10);
- 错误反馈机制:返回 -1 并打印提示,便于调试。
? 注意事项总结
- 字符串索引从 0 开始,务必确保 startIndex + length ≤ len(s);
- 乘法初始值必须为 1,加法才是 0;
- 不要对可能为 nil 的 err 调用 .Error(),应在 err == nil 分支中使用转换结果;
- 对已知格式的纯数字字符串,优先采用 ASCII 算术转换(c - '0'),比 strconv 更安全高效。
运行上述代码,将准确输出 Mult = 238140,即 6×7×1×7×6×5×3×1×3×3 的结果。

















