ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

空文件查找器项目实战:Go 命令行参数排序、目录扫描与文件写入练习精解

空文件查找器项目实战:Go 命令行参数排序、目录扫描与文件写入练习精解 示例工程教程【免费下载链接】learngo❤️ 1000 Hand-Crafted Go Examples, Exercises, and Quizzes. Learn Go by fixing 1000 tiny programs.项目地址https://gitcode.com/gh_mirrors/le/learngo点击查看免费下载导读learngo仓库中的「Empty File Finder空文件查找器」是一个循序渐进的 Go 文件系统实战项目其配套的 17-project-empty-file-finder/exercises/README.md 提供了三个动手练习将命令行参数排序后写入文件、在排序基础上附带序号输出、以及扫描多个目录并把其中的子目录名写入文件。本文以这三道练习为主线逐一给出题目要求、期望输出、参考实现与关键 API 讲解并联动项目正文的三步实现读取空文件 → 写入文件 → 预分配优化帮你打通os.Args、sort.Strings、[]string → []byte转换、ioutil.WriteFile、ioutil.ReadDir、FileInfo.IsDir等核心知识点。读完本文你将能独立完成从命令行取参 → 数据处理 → 落盘写文件的完整 Go 小程序闭环。一、练习总览三道练习分别练什么关联文档列出了三道练习均围绕把处理结果写入文件这一主题展开练习目标核心 API产出文件1-sort-to-a-file排序命令行参数并写入文件os.Args、sort.Strings、ioutil.WriteFilesorted.txt2-sort-to-a-file-2排序并带序号写入文件上一题基础上加strconv.AppendInt、rune 字面量sorted.txt3-print-directories扫描多目录并写入子目录名ioutil.ReadDir、FileInfo.IsDir()dirs.txt每道练习的目录结构一致main.go是留给读者的空模板func main() {}solution/main.go是参考答案。建议先自己实现卡住时再看solution目录。二、练习一排序并写入文件Sort and write items to a file2.1 题目要求参考 练习一模板 中的注释题目拆解为三步从命令行获取参数对参数排序将排序后的切片写入文件。题目给出了三条关键提示记住os.Args的类型是[]string字符串切片可以用sort.Strings直接排序使用ioutil.WriteFile写文件但它的第二参数要求[]byte所以需要先把[]string转换成[]byte新建一个[]byte逐个把字符串元素追加进去。2.2 期望输出# 无参数运行时 $ go run main.go Send me some items and I will sort them # 传入三个单词 $ go run main.go orange banana apple # 查看生成的排序文件 $ cat sorted.txt apple banana orange注意两个细节无参数时打印提示语并正常退出而不是直接 panic每个词在文件中独占一行末尾有换行符。2.3 参考实现与逐段讲解package main import ( fmt io/ioutil os sort ) func main() { items : os.Args[1:] if len(items) 0 { fmt.Println(Send me some items and I will sort them) return } sort.Strings(items) var data []byte for _, s : range items { data append(data, s...) data append(data, \n) } err : ioutil.WriteFile(sorted.txt, data, 0644) if err ! nil { fmt.Println(err) return } }完整源码见 练习一参考答案关键点如下os.Args[1:]取参数os.Args[0]是程序自身路径从索引 1 开始才是用户传入的参数切片表达式天然得到一个[]string。空参数保护len(items) 0时打印提示并return避免后面排序和写文件操作空数据。这是本项目一贯的健壮性写法与项目正文01-fetch-the-files中对os.Args[1:]的判空一致。sort.Strings(items)标准库sort包对字符串切片进行原地升序排序直接修改items本身无需接收返回值。[]string → []byte转换这是本题的核心考点。Go 语言不允许直接强转切片类型因此用一个var data []byte空切片通过append(data, s...)把每个字符串的字节展开追加进去再append(data, \n)补换行。\n是 rune 字面量无类型数值常量可以直接追加进[]byte。ioutil.WriteFile签名是WriteFile(filename string, data []byte, perm os.FileMode)。第三参数0644表示文件权限所有者可读写、组用户和其他用户只读关于 Unix 权限位的计算可参考 02-write-to-a-file/main.go 末尾的注释。文件不存在时会自动创建。错误处理写文件可能失败路径无权限、磁盘满等把err打印出来并return不掩盖错误。三、练习二排序并带序号写入文件Sort and write items to a file with their ordinals3.1 题目要求参考 练习二模板在练习一的基础上为每个排序后的条目加上序号ordinal。期望输出变为$ go run main.go orange banana apple $ cat sorted.txt 1. apple 2. banana 3. orange3.2 题目提示的两个新工具模板注释中提供了两个重要提示strconv.AppendIntstrconv包提供大量把基础类型追加到[]byte的函数。strconv.AppendInt(dst []byte, i int64, base int)会把整数i按base进制格式化后追加到dst末尾并返回新的切片。rune 字面量可直接追加rune 字面量如h、!是无类型数值typeless numerics可以逐个追加到字节切片var slice []byte slice append(slice, h, i, , !) fmt.Printf(%s\n, slice) // 输出: hi !这说明构建文件内容时标点、空格、分隔符都可以用字符字面量直接append而不用写冗长的字符串常量。3.3 参考实现与逐段讲解package main import ( fmt io/ioutil os sort strconv ) func main() { items : os.Args[1:] if len(items) 0 { fmt.Println(Send me some items and I will sort them) return } sort.Strings(items) var data []byte for i, s : range items { data strconv.AppendInt(data, int64(i1), 10) data append(data, ., ) data append(data, s...) data append(data, \n) } err : ioutil.WriteFile(sorted.txt, data, 0644) if err ! nil { fmt.Println(err) return } }完整源码见 练习二参考答案。与练习一相比的差异点循环改用for i, s : range items拿到索引istrconv.AppendInt(data, int64(i1), 10)把从 1 开始的序号按十进制追加进data注意AppendInt要求int64索引i需要显式转换append(data, ., )一次追加两个字符点号和空格体现 rune 字面量批量追加的写法排序与写文件逻辑与练习一完全一致复用了同样的sort.Stringsioutil.WriteFile套路。这道练习的价值在于展示当目标是逐行拼装文本文件内容时[]byteappend组合比反复做字符串拼接更直接、更贴合底层字节操作而strconv的Append*系列函数正是为这种场景设计的。四、练习三查找子目录并写入文件Find and write the names of subdirectories to a file4.1 题目要求参考 练习三模板这道题从排序字符串升级为遍历文件系统从命令行获取多个目录路径把每个目录内部的子目录名追加到一个字节切片把该字节切片写入dirs.txt文件。期望输出示例数据见solution/目录下的dir、dir2结构# 无参数运行时 $ go run main.go Please provide directory paths # 传入两个目录 $ go run main.go dir/ dir2/ # 查看生成的目录清单 $ cat dirs.txt dir/ subdir1/ subdir2/ dir2/ subdir1/ subdir2/ subdir3/4.2 题目提示的新知识点模板注释给出了三条关键指引ioutil.ReadDir一次性读取目录下的所有条目记住在 Go 中目录本身也是一种文件。它返回按文件名排序的[]os.FileInfo。FileInfo.IsDir()os.FileInfo接口的IsDir()方法返回该条目是否为目录。注释建议用go doc os.FileInfo.IsDir或godocc os.FileInfo.IsDir查看文档。\t转义序列用制表符缩进子目录名形成层级感。4.3 参考实现与逐段讲解package main import ( fmt io/ioutil os ) func main() { paths : os.Args[1:] if len(paths) 0 { fmt.Println(Please provide directory paths) return } var dirs []byte for _, dir : range paths { files, err : ioutil.ReadDir(dir) if err ! nil { fmt.Println(err) return } dirs append(dirs, dir...) dirs append(dirs, \n) for _, file : range files { if file.IsDir() { dirs append(dirs, \t) dirs append(dirs, file.Name()...) dirs append(dirs, /, \n) } } dirs append(dirs, \n) } err : ioutil.WriteFile(dirs.txt, dirs, 0644) if err ! nil { fmt.Println(err) return } }完整源码见 练习三参考答案关键点外层循环遍历目录路径每个传入的目录依次处理外层循环内先追加目录名本身和换行再处理其子目录最后追加一个空行分隔不同目录块。ioutil.ReadDir的返回值files是[]os.FileInfo。注意这里每次循环都会读取一个目录ReadDir内部会按文件名排序所以输出是稳定的。file.IsDir()过滤os.FileInfo接口包含Name()、Size()、IsDir()等方法。IsDir()返回true才追加非目录普通文件被跳过。输出格式拼装\t缩进 →file.Name()文件名 →/恢复目录符号 →\n换行。最终的dirs.txt内容与 solution/dirs.txt 示例一致dir/ subdir1/ subdir2/ dir2/ subdir1/ subdir2/ subdir3/错误处理策略任一目录读取失败路径不存在等打印错误并立即return中止整个程序避免产出不完整的文件。练习三把ReadDir枚举目录条目与IsDir()类型判断结合起来是后续文件系统类项目如23-input-scanning、logparser系列中常用的基础能力。五、联动项目正文三道练习背后的三步实战脉络三道练习并非孤立存在它们建立在项目正文 17-project-empty-file-finder 的三个递进步骤之上理解了正文练习的写法就水到渠成5.1 第一步读取并识别空文件01-fetch-the-files/main.go 演示了从命令行取目录 →ioutil.ReadDir枚举 → 用file.Size() 0判断空文件并打印文件名的完整流程配套测试数据在 files 目录下empty1.txt、empty2.txt、empty3.txt为空文件nonEmpty*.txt为非空文件。这道练习练就的os.Args取参与判空模式、ReadDir遍历模式正是三道练习共同的地基。5.2 第二步把结果写入文件02-write-to-a-file/main.go 展示了与练习完全相同的套路先var names []byte声明空字节切片用append(names, name...)和append(names, \n)逐行拼装最后ioutil.WriteFile(out.txt, names, 0644)落盘。该文件还刻意打印了每次append前后的cap(names)直观展示字节切片容量增长——这也是练习中先拼装再一次性写盘而非逐条写文件的原因减少系统调用、内存布局更连续。5.3 第三步预分配优化03-optimize/main.go 进一步展示了性能优化思路先用一个循环统计所有空文件名的总字节数len(file.Name()) 11是为换行符预留再用names : make([]byte, 0, total)一次性预分配足够容量避免append过程中的多次扩容拷贝。这种先算总需求、再一次性分配的模式可以直接迁移到练习一、二如果参数数量巨大可以先估算总长度再make。从项目正文的识别空文件 → 写文件 → 预分配三步到练习的排序写文件 → 排序带序号写文件 → 目录扫描写文件本项目的学习路径始终围绕同一主题不断叠加复杂度命令行取参、[]byte拼装、文件写出是贯穿始终的三大技能点。六、核心 API 速查与常见坑6.1 本组练习用到的标准库 APIAPI作用注意点os.Args[1:]获取命令行参数切片os.Args[0]是程序名取参前先判空sort.Strings(s []string)字符串切片原地升序排序直接修改原切片无返回值ioutil.WriteFile(name, data []byte, perm)将字节切片写入不存在则创建文件第二个参数必须是[]bytestrconv.AppendInt(dst, i int64, base)将整数追加到字节切片i需是int64会返回新的切片ioutil.ReadDir(dir)读取目录条目返回按名排序的[]os.FileInfo目录本身在 Go 中也视为文件os.FileInfo.IsDir()判断条目是否为目录与Size()等方法同属FileInfo接口6.2 常见坑提醒[]string不能直接传给WriteFile必须逐元素展开成[]byte这是练习一的核心训练点strconv.AppendInt的返回值别丢所有Append*函数都可能返回扩容后的新切片必须用返回值重新赋值data strconv.AppendInt(data, ...)文件权限位0644是八进制字面量Go 源码里必须以0开头书写表示文件所有者可读写、组和其他用户只读错误不能静默ReadDir或WriteFile返回err时要打印并退出否则可能生成残缺的输出文件而毫无提示。七、如何运行与验证在任意练习目录下如 1-sort-to-a-file按下列命令验证# 练习一排序写文件 cd 17-project-empty-file-finder/exercises/1-sort-to-a-file/solution go run main.go orange banana apple cat sorted.txt # 期望apple / banana / orange # 练习二排序带序号写文件 cd ../2-sort-to-a-file-2/solution go run main.go orange banana apple cat sorted.txt # 期望1. apple / 2. banana / 3. orange # 练习三扫描目录写子目录名 cd ../3-print-directories/solution go run main.go dir/ dir2/ cat dirs.txt # 期望输出见上一节三道练习的solution目录内均已内置可直接运行的数据练习三自带dir/、dir2/示例目录树。练习时建议先删除或忽略solution目录从空模板main.go开始独立完成再用参考答案对照。通过本组练习你将扎实掌握命令行参数 → 内存数据处理 → 文件系统输出这一 Go 日常工具型程序的完整写法。赞分享示例工程教程【免费下载链接】learngo❤️ 1000 Hand-Crafted Go Examples, Exercises, and Quizzes. Learn Go by fixing 1000 tiny programs.项目地址https://gitcode.com/gh_mirrors/le/learngo点击查看免费下载相关推荐Broot 实战指南在终端里更快地浏览目录、查找文件与执行命令Broot 实战指南在终端里更快地浏览目录、查找文件与执行命令 Broot 是一款以全新方式浏览目录树的开源终端工具你只需敲几个字母就能在保持文件层级可见开发工具Trivy rootfs 命令详解扫描解包文件系统与容器根目录的完整实战指南Trivy rootfs 命令详解扫描解包文件系统与容器根目录的完整实战指南 导读 trivy rootfs 是 Trivy 中专门用于扫描 本地文件系统目录应用安全漏洞扫描SBOM供应链安全云原生YARA 命令行实战指南从规则文件到扫描目标的完整命令手册YARA 命令行实战指南从规则文件到扫描目标的完整命令手册 YARA 的 yara 命令行工具是这款模式匹配引擎最直接的入口它让安全研究员只需一行命令即可用网络安全模式匹配上一篇TeamAI digest周报实战7天团队AI使用趋势报告长什么样下一篇TranslucentTB 实测让 Windows 任务栏透明整块壁纸完整露出来创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表