[GoLang避坑实战-17] 从零撸一个计算器:基础知识的大合练

大家好,我是极客老墨。 学了这么多语法,是时候写个完整项目了。光看代码片段,很难理解 Go 项目是怎么组织的。这篇我们从零开始,写一个命令行工具,看看真实项目的结构和开发流程。 项目目标 我们要做一个简单的命令行计算器,支持基本的数学运算。 功能需求 支持加减乘除运算 命令行参数输入 彩色输出结果 错误处理 技术要点 Go Modules 依赖管理 标准项目结构 包的导入和使用 第三方库集成 交叉编译 初始化项目 第一步是创建项目目录并初始化模块。 创建项目 1cd go-tutorial-code 2# 创建项目目录 3mkdir 15-project-example 4cd 15-project-example 5 6# 初始化 Go Module 7go mod init github.com/gkmz/calc 这里老墨为了教程的需要,把代码放到了 go-tutorial-code, 并且模块名称没有与文件夹名称一致。 生成的 go.mod: 1module github.com/gkmz/calc 2 3go 1.24 要点: 模块名通常是代码仓库地址 go.mod 是项目的起点 初始化后就可以开始写代码了 项目结构 Go 项目有约定俗成的目录结构。 标准布局 115-project-example/ 2├── go.mod # 模块定义 3├── go.sum # 依赖校验 4├── cmd/ # 命令行工具目录 5│ └── calc/ 6│ └── main.go 7├── pkg/ # 可导出的库代码 8│ └── calculator/ 9│ ├── calculator.go 10│ └── calculator_test.go 11├── internal/ # 私有代码(不可被外部导入) 12│ └── utils/ 13│ └── helper.go 14├── README.md # 项目说明 15└── Makefile # 构建脚本(可选) 目录说明: ...

2025-11-10 · 8 min · 1514 words · 老墨

Rust 学习笔记 20:项目实战二:构建 grep 命令行工具 (minigrep)

Rust 学习笔记 20:项目实战二:minigrep “UNIX is basically a simple operating system, but you have to be a genius to understand the simplicity.” – Dennis Ritchie 到目前为止,我们已经学习了 Rust 的大部分核心特性。现在,让我们把它们串起来,复刻一个经典的命令行工具:grep。 我们的目标是创建一个 minigrep,它接受一个查询字符串和一个文件名,然后打印出文件中包含查询字符串的行。 1. 需求分析 用法: 1$ cargo run -- searchstring example-filename.txt 功能点: 读取命令行参数。 读取文件内容。 筛选包含关键词的行。 错误处理(用户没传参数?文件不存在?)。 关注点分离:main.rs 负责处理参数和系统调用,lib.rs 负责核心逻辑。 TDD:测试驱动开发。 环境变量:支持 IGNORE_CASE=1 进行大小写不敏感搜索。 2. 核心代码演进 我们将代码分为 main.rs 和 lib.rs。 2.1 参数解析与配置 在 src/lib.rs 中定义 Config 结构体: 1use std::env; 2 3pub struct Config { 4 pub query: String, 5 pub file_path: String, 6 pub ignore_case: bool, 7} 8 9impl Config { 10 pub fn build(mut args: impl Iterator<Item = String>) -> Result<Config, &'static str> { 11 args.next(); // 也就是程序名,通常忽略 12 13 let query = match args.next() { 14 Some(arg) => arg, 15 None => return Err("Didn't get a query string"), 16 }; 17 18 let file_path = match args.next() { 19 Some(arg) => arg, 20 None => return Err("Didn't get a file path"), 21 }; 22 23 let ignore_case = env::var("IGNORE_CASE").is_ok(); 24 25 Ok(Config { 26 query, 27 file_path, 28 ignore_case, 29 }) 30 } 31} 注意这里使用了 impl Iterator,这样我们可以直接消费 env::args(),更加高效。 ...

2025-11-04 · 2 min · 344 words · 老墨

Rust 学习笔记 10:项目实战一:猜数字

Rust 学习笔记 10:项目实战一:猜数字 “Programming is not about typing, it’s about thinking.” 之前的 9 篇笔记,我们一直在抠语法细节。 今天是圣诞节(假设),我们来点轻松的:用 Rust 写一个猜数字游戏。 规则很简单: 程序生成一个 1~100 的随机数。 玩家输入猜测。 程序提示 “大了”、“小了” 或 “猜对了”。 猜对了游戏结束,否则继续。 1. 引入依赖 Crates Rust 的标准库很精简,没有内置随机数生成。我们需要引入第三方库 rand。 修改 Cargo.toml: 1[dependencies] 2rand = "0.9" 这和 Go 的 go get 不太一样,Rust 更像是 Node.js 的 npm,依赖管理非常现代化。 2. 获取用户输入 1use std::io; 2 3let mut guess = String::new(); // 创建可变空字符串 4 5io::stdin() 6 .read_line(&mut guess) // 传可变引用进去修改 7 .expect("Failed to read line"); // 处理 Result::Err 注意那个 read_line 返回的是 io::Result 枚举。如果读取失败,它会返回 Err,expect 方法会帮你 panic 并打印错误信息。在 Rust 中,忽略返回值是会被警告的。 ...

2024-12-25 · 2 min · 249 words · 老墨