
fmt.Scanln 会截断空格后的输入,导致 strings.Split 无法获得完整字符串;应改用 bufio.Scanner 读取整行,再分割处理。
`fmt.scanln` 会截断空格后的输入,导致 `strings.split` 无法获得完整字符串;应改用 `bufio.scanner` 读取整行,再分割处理。
在 Go 中,strings.Split(s, " ") 本身完全正常——它始终返回 []string(切片),但前提是传入的字符串 s 包含预期的分隔内容。问题根源不在 Split,而在于上游输入读取方式:fmt.Scanln 遇到首个空白字符(空格、制表符、换行符)即停止扫描,仅读取第一个单词。
例如,当用户输入 "2 3" 时,fmt.Scanln(&in) 实际只将 "2" 赋值给 in,in 的值为 "2"(末尾无空格),strings.Split("2", " ") 返回 []string{"2"},此时访问 wh[1] 必然触发 panic:index out of range [1] with length 1。
✅ 正确做法是使用 bufio.Scanner 读取整行(包括空格分隔的多个字段):
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
var seedCost float64
var lawnNo int
// 使用 bufio.Scanner 安全读取整行
scanner := bufio.NewScanner(os.Stdin)
// 读取 seedCost
scanner.Scan()
seedCost, _ = strconv.ParseFloat(scanner.Text(), 64)
// 读取 lawnNo
scanner.Scan()
lawnNo, _ = strconv.Atoi(scanner.Text())
lawnCost := 0.00
for i := 0; i < lawnNo; i++ {
scanner.Scan()
in := scanner.Text() // ✅ 完整读取一行,如 "2 3"
wh := strings.Split(in, " ") // 得到 []string{"2", "3"}
// 建议添加长度校验,避免运行时 panic
if len(wh) < 2 {
fmt.Fprintf(os.Stderr, "警告:输入格式错误,期望至少两个数字,得到 %v\n", wh)
continue
}
w, err1 := strconv.ParseFloat(wh[0], 64)
h, err2 := strconv.ParseFloat(wh[1], 64)
if err1 != nil || err2 != nil {
fmt.Fprintf(os.Stderr, "解析错误:w=%q, h=%q\n", wh[0], wh[1])
continue
}
area := w * h
lawnCost += area * seedCost
}
ans := strconv.FormatFloat(lawnCost, 'E', 8, 64)
fmt.Println(ans)
}⚠️ 注意事项:
-
fmt.Scanln适用于简单单值输入,不适用于含空格的复合输入; -
bufio.Scanner默认按行分割,scanner.Text()返回不含换行符的纯字符串,适合后续strings.Split; - 务必检查
strings.Split结果长度(如len(wh) >= 2),并在strconv转换时处理错误,避免程序崩溃; - 若需更健壮的输入解析(如跳过空行、忽略首尾空格),可结合
strings.Fields(in)(自动按任意空白符分割并剔除空字符串)。
掌握输入读取与字符串分割的协作逻辑,是编写稳定命令行工具的关键一步。

















