
本文详解如何使用 go 语言安全、可靠地从标准输入读取用户指定的目录路径,并列出其下所有文件和子目录名称,重点解决换行符残留、错误忽略等常见陷阱。
在 Go 中通过标准输入获取目录路径并读取其内容,看似简单,实则容易因输入处理不当而失败。你提供的代码始终返回空切片 [],根本原因在于 bufio.NewReader.ReadString('\n') 会将换行符 \n(Windows 下可能是 \r\n)一并包含在字符串中——例如用户输入 ./data 后按回车,实际得到的是 "./data\n"。此时调用 ioutil.ReadDir("./data\n") 自然失败,因为该路径不存在。
此外,原代码忽略了所有错误(使用 _ 丢弃 error 返回值),导致问题难以定位。现代 Go 开发中,绝不应忽略 I/O 或系统调用错误;它们是调试的第一线索。
以下是修复后的完整、健壮实现(已升级为 Go 1.16+ 推荐方式,使用 os.ReadDir 替代已弃用的 ioutil.ReadDir):
package main
import (
"bufio"
"fmt"
"os"
"path/filepath"
"strings"
)
func main() {
fmt.Print("directory: ")
scanner := bufio.NewScanner(os.Stdin)
if !scanner.Scan() {
fmt.Fprintln(os.Stderr, "error: failed to read input")
os.Exit(1)
}
dirPath := strings.TrimSpace(scanner.Text()) // ✅ 安全去除首尾空白(含 \n, \r, \t)
if dirPath == "" {
fmt.Fprintln(os.Stderr, "error: empty directory path provided")
os.Exit(1)
}
// 检查路径是否存在且为目录
info, err := os.Stat(dirPath)
if err != nil {
fmt.Fprintf(os.Stderr, "error: cannot access %q — %v\n", dirPath, err)
os.Exit(1)
}
if !info.IsDir() {
fmt.Fprintf(os.Stderr, "error: %q is not a directory\n", dirPath)
os.Exit(1)
}
// 读取目录条目(Go 1.16+ 推荐方式)
entries, err := os.ReadDir(dirPath)
if err != nil {
fmt.Fprintf(os.Stderr, "error: failed to read directory %q — %v\n", dirPath, err)
os.Exit(1)
}
// 仅打印文件/目录名(不含路径)
fmt.Println("Files and directories:")
for _, entry := range entries {
fmt.Println(entry.Name())
}
}✅ 关键改进说明:
- 使用 strings.TrimSpace() 替代手动 strings.Replace,可同时清除 \n、\r、空格等各类空白符,更鲁棒;
- 显式检查 os.Stat 结果,确保路径存在且为目录,避免后续操作静默失败;
- 使用 os.ReadDir(替代已废弃的 ioutil.ReadDir),性能更好、语义更清晰;
- 所有错误均输出到 os.Stderr 并终止程序,符合 CLI 工具最佳实践;
- 最终仅输出条目名称(entry.Name()),如需完整路径可用 filepath.Join(dirPath, entry.Name())。
⚠️ 注意事项:
- 该程序不递归遍历子目录;如需递归,请改用 filepath.WalkDir;
- 在 Windows 上注意路径分隔符兼容性(filepath.Join 和 os.Stat 可自动处理,无需手动替换 / 和 \);
- 若需过滤特定类型(如仅文件或仅 .txt 文件),可在 for 循环内添加 entry.IsDir() 或 strings.HasSuffix(entry.Name(), ".txt") 判断。
掌握路径输入清洗与错误驱动开发(Error-Driven Development),是编写稳定 Go 系统工具的关键一步。










