# Go 学习路线图

> 从本项目 `SRemoteConnectClient` 中提取，按文件+主题整理

---

## 一、Go 语言基础

| 主题 | 出现位置 | 说明 |
|------|----------|------|
| `package main` + `main()` | main.go:15 | 程序入口，可执行程序必须的 |
| `import` 包管理 | main.go:4-8 | 引入标准库和第三方库，依赖在 go.mod/go.sum |
| `var` 全局变量 | main.go:12, logger.go:14 | 包级别可访问变量 |
| `var` 分组声明 | Perm.go:13-18, console_windows.go:8-14 | 一次性声明多个相关变量 |
| `const` 常量 | console_windows.go:16-19 | 编译期确定的不可变值 |
| `struct` 结构体 | Perm.go:10, EasyTier.go:7 | 自定义数据类型 |
| 零值初始化 `Xxx{}` | EasyTier.go:7, DoConnect.go:22 | 空结构体作命名空间 |
| 构造函数 `NewXxx()` | Perm.go:20 | Go 惯用的工厂模式 |
| 方法 (接收者) | Perm.go:23, EasyTier.go:12 | `func (p *Type) Method()` |
| 指针接收者 vs 值接收者 | EasyTier.go:12 | `*Type` 可修改原值 |
| 条件分支 `if-else` | main.go:23-27 | 流程控制 |
| `return` 提前退出 | main.go:26 | 提前返回函数 |
| `for range` 循环 (Go 1.22+) | trayicon_windows.go:88-89 | `for y := range h` 新语法 |
| `defer` 延迟执行 | main.go:34 | 函数返回前自动执行，用于清理资源 |
| 错误处理 `if err != nil` | main.go:97 | Go 的错误处理模式 |
| `panic` 不可恢复错误 | logger.go:26 | 程序终止 |
| `make` / `new` 分配内存 | trayicon_windows.go:86 | make 用于 slice/map/chan |

### 指针

| 主题 | 位置 | 说明 |
|------|------|------|
| `*os.Process` 指针类型 | DoConnect.go:14 | 作为返回值 |
| `&` 取地址 | DoConnect.go:63 | 获取变量地址 |
| `unsafe.Pointer` | Perm.go:44-48 | 通用指针，用于 WinAPI |

---

## 二、并发编程 (goroutine + channel)

| 主题 | 位置 | 说明 |
|------|------|------|
| `go func() {}` | main.go:61 | 启动一个 goroutine (轻量级并发) |
| `<-channel` | main.go:62 | 从 channel 阻塞读取 |
| `make(chan error, 1)` | DoConnect.go:72 | 创建带缓冲的 channel |
| `select` 多路复用 | DoConnect.go:76 | 同时等待多个 channel |
| `time.After` 超时 | DoConnect.go:80 | 超时 channel |
| goroutine + channel + select | DoConnect.go:71-80 | 经典超时等待模式 |
| 回调函数 | main.go:38 | 函数作为参数传入 |

---

## 三、os/exec 子进程管理

| 主题 | 位置 | 说明 |
|------|------|------|
| `exec.Command(name, args...)` | DoConnect.go:58, 92 | 创建命令 (名字+参数分开传) |
| `cmd.Dir` | DoConnect.go:59 | 设置子进程工作目录 |
| `cmd.Stdout/Stderr` | DoConnect.go:62-64 | 捕获子进程输出 |
| `cmd.Start()` | DoConnect.go:66 | 非阻塞启动 |
| `cmd.Wait()` | DoConnect.go:74 | 等待进程结束 |
| `cmd.Run()` | DoConnect.go:92 | 启动 + 等待一步完成 |
| `process.Pid` | DoConnect.go:84 | 获取进程 PID |
| `process.Kill()` | main.go:98 | 终止进程 |
| `strings.Fields` 拆分命令行 | DoConnect.go:49 | 字符串按空格分割 |
| `...` 切片展开 | DoConnect.go:58 | `parts[1:]...` 展开为参数 |
| `bytes.Buffer` 捕获输出 | DoConnect.go:5, 62 | 内存缓冲区 |

---

## 四、文件与路径操作

| 主题 | 位置 | 说明 |
|------|------|------|
| `filepath.Join` | DoConnect.go:10 | 跨平台路径拼接 |
| `filepath.Dir` | DoConnect.go:40 | 获取目录部分 |
| `os.Executable()` | DoConnect.go:35 | 获取当前可执行文件路径 |
| `os.Getwd()` | logger.go:20 | 获取当前工作目录 |
| `os.Stat()` | DoConnect.go:52 | 检查文件是否存在 |
| `os.IsNotExist()` | DoConnect.go:52 | 判断文件不存在错误 |
| `os.ReadFile()` | trayicon_windows.go:22 | 一次性读取文件 |
| `os.OpenFile()` | logger.go:33 | 创建/追加模式打开文件 |
| `os.MkdirAll()` | logger.go:25 | 递归创建目录 |

---

## 五、第三方库

### 5.1 systray (系统托盘)

| 主题 | 位置 | 说明 |
|------|------|------|
| `go get` 安装 | main.go:8 | `github.com/getlantern/systray` |
| `systray.Run(onReady, onExit)` | main.go:38 | 启动托盘 (阻塞) |
| `systray.SetIcon(data)` | main.go:45 | 设置托盘图标 |
| `systray.SetTooltip(text)` | main.go:48 | 悬停提示文字 |
| `systray.AddMenuItem(name, tooltip)` | main.go:49-54 | 添加右键菜单项 |
| `systray.AddSeparator()` | main.go:52 | 菜单分隔线 |
| `item.Disable()` | main.go:51 | 禁用菜单项 |
| `item.ClickedCh` | main.go:62 | channel，点击时收到信号 |
| `systray.Quit()` | main.go:63 | 退出托盘 |

### 5.2 zerolog (日志)

| 主题 | 位置 | 说明 |
|------|------|------|
| `github.com/rs/zerolog` | logger.go:11 | 高性能结构化日志 |
| `zerolog.ConsoleWriter` | logger.go:40 | 控制台可读输出 (带颜色) |
| `io.MultiWriter` | logger.go:46 | 同时写文件和屏幕 |
| 链式配置 | logger.go:49-51 | `New().With().Timestamp().Caller()` |
| 链式日志调用 | DoConnect.go:30-32 | `Info().Str(key, val).Msg(msg)` |

---

## 六、Windows API 调用

| 主题 | 位置 | 说明 |
|------|------|------|
| `syscall.NewLazyDLL()` | Perm.go:15 | 延迟加载 DLL |
| `dll.NewProc()` | Perm.go:16-17 | 获取函数指针 |
| `proc.Call()` | Perm.go:24 | 调用 WinAPI (返回 `(ret, _, _)`) |
| `syscall.UTF16PtrFromString()` | Perm.go:36-38 | Go 字符串 → UTF-16 指针 |
| `unsafe.Pointer` | Perm.go:44-48 | 通用指针传递 |
| `syscall.GetLastError()` | Perm.go:52 | 获取 Windows 错误码 |
| `ShellExecuteW("runas")` | Perm.go:42-49 | UAC 提权 |
| `IsUserAnAdmin` | Perm.go:24 | 检查管理员权限 |
| `GetConsoleWindow` | console_windows.go:13 | 获取控制台句柄 |
| `ShowWindowAsync` | console_windows.go:14 | 显示/隐藏窗口 |
| `kernel32.dll` | console_windows.go:10 | 核心 WinAPI |
| `user32.dll` | console_windows.go:12 | 用户界面 API |

---

## 七、图像处理

| 主题 | 位置 | 说明 |
|------|------|------|
| `image.Decode` / `png.Decode` | trayicon_windows.go:29 | PNG 字节解码为图像对象 |
| `png.Encode` | trayicon_windows.go:40 | 图像对象编码为 PNG 字节 |
| `image.NewRGBA` | trayicon_windows.go:86 | 创建画布 |
| `image.Rect` | trayicon_windows.go:86 | 定义矩形 |
| `src.Bounds()` | trayicon_windows.go:87 | 获取图像尺寸 |
| `dst.Set(x, y, color)` | trayicon_windows.go:92 | 写像素 |
| `src.At(x, y)` | trayicon_windows.go:92 | 读像素 |
| `bytes.NewReader` | trayicon_windows.go:29 | 字节 → io.Reader |
| `bytes.Buffer` | trayicon_windows.go:39 | 内存缓冲区 (io.Writer) |
| `encoding/binary` | trayicon_windows.go:5 | 二进制数据处理 |
| ICO 格式包装 | trayicon_windows.go:52-82 | PNG 包 ICO 头以兼容 Windows |
| `//go:embed` (推荐) | icon_bytes.go:3 | Go 1.16+ 内嵌资源指令 |

---

## 八、其他标准库

| 主题 | 位置 | 说明 |
|------|------|------|
| `fmt.Sprintf` | EasyTier.go:13 | 格式化字符串 `%s` 占位符 |
| `time.Now()` | logger.go:30 | 当前时间 |
| `time.Format()` | logger.go:30 | 格式化时间 ("2006-01-02") |
| `time.After` | DoConnect.go:80 | 超时 channel |
| `os` 包 | 多个文件 | 操作系统接口 |
| `strings.Fields` | DoConnect.go:49 | 按空白字符分割 |
| `io.MultiWriter` | logger.go:46 | 写多个目标 |

---

## 九、建议学习顺序

```
第1周: Go 基础 (package, import, var, func, struct, if, for, return)
第2周: 错误处理, defer, 指针 (&, *, 接收者方法)
第3周: 文件操作 (os, filepath), 字符串处理 (fmt, strings)
第4周: goroutine + channel + select (并发核心)
第5周: os/exec 子进程管理
第6周: syscall + WinAPI 调用
第7周: 第三方库 (systray, zerolog)
第8周: 图像处理 (image/png, binary)
```
