Ver código fonte

refactor: organize numbered lessons and document Go entry point

zhuts 4 dias atrás
pai
commit
197dbff561
5 arquivos alterados com 220 adições e 55 exclusões
  1. 40 18
      INSTALL.md
  2. 52 37
      README.md
  3. 128 0
      lessons/01_hello/README.md
  4. 0 0
      lessons/01_hello/main.go
  5. 0 0
      lessons/01_hello/main_test.go

+ 40 - 18
INSTALL.md

@@ -46,7 +46,7 @@ go env GOROOT GOPATH
 1. 从 <https://code.visualstudio.com/> 安装 VS Code。
 2. 扩展面板(`Ctrl + Shift + X`)搜索 `golang.Go`,安装由 Go Team at Google 发布的 Go 扩展。
 3. 使用“打开文件夹”打开本项目根目录。
-4. 打开 `main.go`,根据提示安装所需工具;或按 `Ctrl + Shift + P`,执行 `Go: Install/Update Tools`。
+4. 打开 `lessons/01_hello/main.go`,根据提示安装所需工具;或按 `Ctrl + Shift + P`,执行 `Go: Install/Update Tools`。
 5. 安装 `gopls`;需要 F5 断点调试时再安装 `dlv`。
 
 也可手动安装这些**开发工具**(需要网络,不属于项目运行依赖):
@@ -64,7 +64,9 @@ go install github.com/go-delve/delve/cmd/dlv@latest
 
 ### 已经打开当前项目
 
-直接在项目根目录打开终端即可。仓库已有 `go.mod`,**不要重复执行 `go mod init`**。
+直接在项目根目录打开终端即可。仓库已有公共 `go.mod`,所有例程共用它,**不要在根目录或例程目录重复执行 `go mod init`**。
+
+每个例程独占 `lessons/编号_主题/` 目录,拥有自己的程序、测试和说明。根目录只放公共配置及教程,不放程序入口。
 
 ### 在新电脑克隆
 
@@ -102,10 +104,10 @@ go env GOPROXY
 
 ## 5. 运行第一个程序
 
-在项目根目录执行:
+在项目根目录指定第 01 课的目录:
 
 ```powershell
-go run .
+go run ./lessons/01_hello
 ```
 
 预期输出:
@@ -116,9 +118,16 @@ go run .
 2 + 3 = 5
 ```
 
-这里的 `.` 表示当前目录的包。修改代码并保存后,再次运行该命令即可。
+修改代码并保存后,再次运行该命令即可。也可以从项目根目录进入本课:
+
+```powershell
+Set-Location lessons/01_hello
+go run .
+```
 
-也可用 `go run main.go` 运行当前单文件示例,但后续程序拆分为多个文件时,优先使用 `go run .`,避免遗漏其他源码文件。
+这里的 `.` 表示当前例程所在的包,能包含本课目录中的多个源码文件。根目录没有 Go 程序入口,不要在根目录执行 `go run .`。每次只运行一课,不使用 `go run ./...` 同时启动所有例程。
+
+下文公共命令按项目根目录执行;如果刚进入本课,可用 `Set-Location ../..` 返回根目录。
 
 ## 6. 格式化、测试与检查
 
@@ -126,7 +135,10 @@ go run .
 # 格式化所有包
 go fmt ./...
 
-# 运行表驱动单元测试
+# 只测试第 01 课
+go test -v ./lessons/01_hello
+
+# 测试所有课程
 go test -v ./...
 
 # 查看测试覆盖率
@@ -136,35 +148,45 @@ go test -cover ./...
 go vet ./...
 ```
 
-`main_test.go` 验证了正数、零、负数和正负混合相加。`_test.go` 文件不会被编译进正常程序。覆盖率可能不到 100%,因为当前只为加法函数写了测试,没有对终端输出入口做测试。
+`lessons/01_hello/main_test.go` 验证了正数、零、负数和正负混合相加。`_test.go` 文件不会被编译进正常程序。覆盖率可能不到 100%,因为当前只为加法函数写了测试,没有对终端输出入口做测试。
 
 ## 7. 编译为 Windows 可执行文件
 
-在 PowerShell 执行:
+在项目根目录的 PowerShell 执行,每课使用单独的产物目录:
 
 ```powershell
-# 创建构建输出目录,重复执行也可以
-New-Item -ItemType Directory -Force bin | Out-Null
+# 创建第 01 课的构建输出目录,重复执行也可以
+New-Item -ItemType Directory -Force bin/01_hello | Out-Null
 
-# 编译
-go build -o ./bin/hello.exe .
+# 只编译第 01 课
+go build -o ./bin/01_hello/hello.exe ./lessons/01_hello
 
 # 启动编译后的程序
-.\bin\hello.exe
+.\bin\01_hello\hello.exe
 ```
 
+命令解释:
+
+- `go build` 是编译命令。
+- `-o ./bin/01_hello/hello.exe` 指定输出文件的路径和名称。
+- `./lessons/01_hello` 指定要编译的例程目录。
+- `go run ./lessons/01_hello` 则是先编译再立即运行,不会在指定输出目录保留可执行文件,并不是解释执行。
+- 修改源码后,需要重新执行编译命令;已经生成的可执行文件不会自动变化。
+
+Go 与 C 类似,也有主函数入口:可执行程序使用 `package main`,并声明无参数、无返回值的 `func main()`。它不需要 C 中的 `return 0`,源码也不一定必须叫 `main.go`。详细示例和 C / Go 对照见 [第 01 课:主函数入口](./lessons/01_hello/README.md#go-也有-main-主函数吗)。
+
 编译成功时通常没有额外输出。PowerShell 运行当前目录下的程序需要 `./` 或 `.\` 前缀,不能只输入 `hello.exe`。
 
 编译后的程序可以在兼容的 Windows 和 CPU 架构环境运行,一般不需要目标电脑安装 Go SDK。本项目没有 C 语言依赖。`bin` 已加入 Git 忽略规则,不提交可执行文件。
 
 ## 8. 在 VS Code 中调试
 
-1. 打开 `main.go`,在函数内的可执行语句左侧点击,添加断点。
+1. 打开 `lessons/01_hello/main.go`,在函数内的可执行语句左侧点击,添加断点。
 2. 按 F5,如提示安装 Delve 则按提示安装。
-3. 如需选择调试配置,选择 Go 的当前包(Launch Package)模式。
+3. 如需选择调试配置,选择 Go 的当前包(Launch Package)模式,目标应是当前文件所在的例程目录(`${fileDirname}`),不是仓库根目录。
 4. 用 F10 单步执行,观察变量 `a`、`b` 的值。
 
-优先先确认终端 `go run .` 能正常执行,再排查编辑器调试问题。不需要额外安装 Code Runner 扩展。
+优先先确认在根目录运行 `go run ./lessons/01_hello` 能正常执行,再排查编辑器调试问题。不需要额外安装 Code Runner 扩展。
 
 ## 9. 日常 Git 提交流程
 
@@ -173,7 +195,7 @@ go build -o ./bin/hello.exe .
 ```powershell
 git status
 git diff
-git add README.md INSTALL.md main.go main_test.go go.mod .gitignore
+git add -A -- README.md INSTALL.md lessons go.mod .gitignore
 git commit -m "docs: update Go learning notes"
 git push
 ```

+ 52 - 37
README.md

@@ -1,14 +1,39 @@
-# Go 语言学习与测试
+# Go 语言分级学习与测试
 
-用于学习 Go 基础语法、运行示例、编写单元测试和练习编译发布的个人学习仓库。
+按编号逐级学习,**每个例程独占一个文件夹**,代码、测试和该例程说明放在一起,不与其他例程混放。
+
+## 项目结构
+
+```text
+.
+├── README.md               # 学习目录与公共命令
+├── INSTALL.md              # 环境、依赖、编译运行教程
+├── go.mod                  # 所有例程共用的模块配置
+├── .gitignore
+└── lessons/
+    └── 01_hello/           # 第 01 课:第一个 Go 程序
+        ├── README.md       # 本课目标、运行方法与练习
+        ├── main.go         # 本课独立入口
+        └── main_test.go    # 本课测试
+```
+
+根目录不放例程代码。各课共享根目录的 `go.mod`,不需要逐课初始化模块,也不需要 `go.work`。当前模块路径 `example.com/go-study` 是学习用标识,不必与 Git 地址相同。
+
+## 学习目录
+
+| 级别 | 例程 | 内容 | 状态 |
+| --- | --- | --- | --- |
+| 01 | [第一个 Go 程序](./lessons/01_hello/README.md) | 输出、变量、函数、首次测试 | 已建立 |
+
+后续按 `02_variables`、`03_conditions`、`04_loops` 等编号逐步新增独立目录,这些是命名示例,目前尚未创建。不一次性铺开后续课程,也不把新例程写进旧例程的入口文件。
 
 ## 快速开始
 
-安装 Go SDK 后,在本目录的终端执行:
+在项目根目录执行:
 
 ```powershell
 go version
-go run .
+go run ./lessons/01_hello
 ```
 
 预期输出:
@@ -19,53 +44,43 @@ go run .
 2 + 3 = 5
 ```
 
-本项目仅使用 Go 标准库,**不需要安装第三方运行依赖**。完整安装步骤、工具依赖、编译运行方法及常见问题见 [安装与运行教程](./INSTALL.md)。
+也可以进入本课目录运行:
 
-## 项目结构
-
-```text
-.
-├── README.md       # 项目说明
-├── INSTALL.md      # 安装、依赖、运行、测试与编译教程
-├── go.mod          # Go 模块与工具链版本要求
-├── main.go         # 第一个程序:输出、变量与加法函数
-├── main_test.go    # Sum 函数的表驱动单元测试
-└── .gitignore      # 忽略编译产物和本地配置
+```powershell
+Set-Location lessons/01_hello
+go run .
+go test -v .
 ```
 
-当前模块路径为 `example.com/go-study`,是本地学习用的模块标识,不需要注册域名,与 Git 远程地址可以不同。
+> 根目录没有 Go 程序入口,不要在根目录使用 `go run .`。进入具体例程目录后才使用该命令。
 
-## 常用命令
+## 公共命令
+
+以下命令均在**项目根目录**执行:
 
 ```powershell
-# 编译并运行
-go run .
+# 只运行第 01 课
+go run ./lessons/01_hello
 
-# 格式化
-go fmt ./...
+# 只测试第 01 课
+go test -v ./lessons/01_hello
 
-# 单元测试与静态检查
+# 格式化、测试、检查所有课程
+go fmt ./...
 go test -v ./...
 go vet ./...
 
-# 编译并运行 Windows 可执行文件
-New-Item -ItemType Directory -Force bin | Out-Null
-go build -o ./bin/hello.exe .
-.\bin\hello.exe
+# 编译第 01 课到对应的构建目录
+New-Item -ItemType Directory -Force bin/01_hello | Out-Null
+go build -o ./bin/01_hello/hello.exe ./lessons/01_hello
+.\bin\01_hello\hello.exe
 ```
 
-`go run` 会先编译再运行;`go build` 生成可以单独启动的可执行文件。
-
-## 学习路线
+每个例程独立编译运行,不要使用 `go run ./...` 尝试一次启动所有课程。构建产物统一放入已忽略的 `bin/课程编号/` 目录。
 
-1. 读懂入口函数 `main`、导入语句 `import`、变量声明 `:=`。
-2. 修改输出和加法函数,学习参数、返回值与类型。
-3. 运行测试,为新函数补充更多测试用例。
-4. 练习条件判断、循环、数组、切片和 map。
-5. 继续学习结构体、接口、错误处理、文件与 JSON。
-6. 最后学习 goroutine、channel 和简单 HTTP 服务。
+## 安装与依赖
 
-后续独立练习建议分别放在 `cmd/hello`、`cmd/variables` 等子目录中,使用 `go run ./cmd/hello` 运行;不要在同一个包中重复声明 `main` 函数。
+当前仅使用 Go 标准库,**不需要第三方运行依赖**。详见 [安装与运行教程](./INSTALL.md),包含 SDK、VS Code 工具安装、依赖管理、编译、测试和调试步骤。
 
 ## 参考资料
 
@@ -77,4 +92,4 @@ go build -o ./bin/hello.exe .
 
 远程地址:<http://vk-fly.com:10880/ZhuTianShuai/go_learn.git>
 
-请勿将密码、访问令牌或个人环境配置提交到仓库。当前提供的是 HTTP 地址,不能提供 HTTPS 的传输加密;如服务端支持,建议后续改用 HTTPS 或 SSH。
+请勿提交密码、访问令牌或个人环境配置。当前 HTTP 地址没有 HTTPS 传输加密;如服务端支持,建议改用 HTTPS 或 SSH。

+ 128 - 0
lessons/01_hello/README.md

@@ -0,0 +1,128 @@
+# 第 01 课:第一个 Go 程序
+
+## 学习目标
+
+先跑通程序,再初步认识入口函数、标准输出、变量和函数。测试代码作为配套示范,不要求第一遍就掌握表驱动测试。
+
+## 本课文件
+
+- [main.go](./main.go):本课程序入口和 `Sum` 加法函数。
+- [main_test.go](./main_test.go):验证加法函数的 4 组测试。
+
+本课与其他例程相互独立,共享仓库根目录的 `go.mod`,不要在这里再次执行 `go mod init`。
+
+## 运行方法
+
+方式一:在仓库根目录执行:
+
+```powershell
+go run ./lessons/01_hello
+```
+
+方式二:从仓库根目录进入本课,再运行:
+
+```powershell
+Set-Location lessons/01_hello
+go run .
+```
+
+两种方式输出相同:
+
+```text
+你好,Go!
+欢迎开始 Go 语言学习与测试。
+2 + 3 = 5
+```
+
+## 阅读顺序
+
+1. `package main`:声明这是可执行程序所在的包。
+2. `import "fmt"`:引入标准库中的格式化输出包,不需要额外安装。
+3. `func main()`:程序启动入口。
+4. `fmt.Println`:输出一行文字。
+5. `a, b := 2, 3`:声明并初始化两个整数变量。
+6. `Sum(a, b)`:调用自定义函数并获得返回值。
+7. `fmt.Printf`:按格式输出,`%d` 代表整数,`\n` 代表换行。
+
+## Go 也有 main 主函数吗?
+
+有,和 C 类似,Go 可执行程序也通过 `main` 函数进入主要逻辑:
+
+```go
+package main // 可执行程序必须属于 main 包
+
+import "fmt"
+
+func main() { // 主函数入口
+    fmt.Println("你好,Go!")
+}
+```
+
+| 对比项 | C | Go |
+| --- | --- | --- |
+| 常见入口声明 | `int main(void)` | `func main()` |
+| 入口返回值 | 返回整数退出码,通常写 `return 0;` | 不声明返回值,不需要 `return 0` |
+| 标准输出 | `printf(...)` | `fmt.Printf(...)` 或 `fmt.Println(...)` |
+
+注意:
+
+- 可执行程序需要 `package main` 和包级 `func main()`,入口不由文件名决定;源码不一定必须叫 `main.go`。
+- 同一个例程所在的包只能有一个包级 `main` 函数,不同目录的例程可以各有自己的 `main`。
+- `main` 不接收参数,也没有返回值。命令行参数可通过标准库 `os.Args` 获取;需要指定退出码时可使用 `os.Exit`,后续课程再学习。
+- 更准确地说,Go 会先完成包级变量初始化和 `init` 函数执行,再调用 `main`;当前课程没有自定义 `init`,先理解主函数入口即可。
+
+## 本课测试
+
+在仓库根目录执行:
+
+```powershell
+go test -v ./lessons/01_hello
+```
+
+如果终端已经在本课目录,执行:
+
+```powershell
+go test -v .
+```
+
+测试覆盖正数、零、负数、正负混合相加。`_test.go` 文件不会进入正常的可执行程序。
+
+## 编译与运行的区别
+
+编译指令是 **`go build`**。以下命令在仓库根目录执行:
+
+```powershell
+# 创建输出目录,第一次编译时执行,重复执行也可以
+New-Item -ItemType Directory -Force bin/01_hello | Out-Null
+
+# 编译第一课,生成可执行文件
+go build -o ./bin/01_hello/hello.exe ./lessons/01_hello
+
+# 运行编译后的程序
+.\bin\01_hello\hello.exe
+```
+
+逐项解释:
+
+- `go build`:编译程序。
+- `-o ./bin/01_hello/hello.exe`:指定生成的可执行文件路径和名称。
+- `./lessons/01_hello`:要编译的例程目录,编译的是本课的包,不是其他课程。
+- `.\bin\01_hello\hello.exe`:启动生成的程序;PowerShell 执行本地文件需要路径前缀。
+
+如果只想快速运行,不需要保留可执行文件:
+
+```powershell
+go run ./lessons/01_hello
+```
+
+`go run` 也是**先编译再运行**,不是解释执行;`go build` 则把可执行文件保留在指定位置,之后可以多次直接启动。编译后修改源码,需要重新编译,已有的可执行文件不会自动更新。
+
+## 动手练习
+
+- [ ] 成功运行程序。
+- [ ] 把欢迎语修改成自己的文字并再次运行。
+- [ ] 修改 `a`、`b` 的值,观察计算结果。
+- [ ] 运行测试,确认所有用例通过。
+- [ ] 尝试解释 `main` 与 `Sum` 两个函数各自的作用。
+
+完成后再新增第 02 课目录;不要把下一课代码堆进本课。环境安装和公共教程见 [安装与运行教程](../../INSTALL.md),课程目录见 [学习总览](../../README.md)。

+ 0 - 0
main.go → lessons/01_hello/main.go


+ 0 - 0
main_test.go → lessons/01_hello/main_test.go