vault backup: 2026-07-01 23:09:21

This commit is contained in:
2026-07-01 23:09:21 +08:00
parent 0fca751850
commit a5e418c701
8 changed files with 1380 additions and 0 deletions
+271
View File
@@ -0,0 +1,271 @@
---
tags: [macos, dev-env, onboarding]
create time: 2026-07-01 00:00
---
# macOS 开发环境配置指南
## 概述
面向 Mac 的通用开发环境搭建步骤,覆盖七牛云暑期实习开营前的工具链要求:Git / SSH、Node.js(nvm + pnpm)、TypeScript、Go(GOPROXY)、AI Coding Agent 和 GitHub CLI。按顺序执行即可,每条末尾附验证命令。
## 前置条件
- macOS 12 Monterey 或更高版本
- 系统自带 **Terminal**,推荐使用 **iTerm2**
```bash
brew install iterm2
```
## 一、Homebrew
详见 [[mac-dev-env-setup/homebrew-intro]](安装步骤与常见命令在此简述,进阶用法见独立文档)。
Homebrew 是 macOS 最重要的包管理器,后续所有工具都通过它安装。
```bash
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```
首次安装后把 brew 加入 PATH(ARM Mac / Intel Mac 不同,按终端输出的提示操作):
```bash
# ARM Mac(M1/M2/M3/M4)
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile
eval "$(/opt/homebrew/bin/brew shellenv)"
# Intel Mac
echo 'export PATH="/usr/local/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc
```
验证:
```bash
brew --version
```
### 常用 brew 命令速查
| 用途 | 命令 |
|------|------|
| 搜索 | `brew search <name>` |
| 安装 | `brew install <name>` |
| 卸载 | `brew uninstall <name>` |
| 升级所有已装包 | `brew upgrade` |
| 清理缓存 | `brew cleanup` |
| 列出可升级包 | `brew outdated` |
## 二、Git & SSH
详见 [[mac-dev-env-setup/git-ssh-config]](双账号密钥路由、~/.ssh/config 配置机制、连接排障)。
```bash
brew install git
git --version # 验证
```
### SSH Key 生成速查
```bash
# GitHub
ssh-keygen -t ed25519 -C "hezhaohui0807@163.com" -f ~/.ssh/id_ed25519_github
# Gitea
ssh-keygen -t ed25519 -C "hezhaohui0807@163.com" -f ~/.ssh/id_ed25519_gitea
```
公钥分别粘贴到对应平台的 SSH Keys 设置页。详细 Host 别名配置见子文档。
### Git 基础配置
```bash
git config --global user.name "hezhaohui"
git config --global user.email "hezhaohui0807@163.com"
git config --global core.autocrlf input
git config --global init.defaultBranch main
```
## 三、Node.js + pnpm
详见 [[mac-dev-env-setup/node-nvm-pnpm]](nvm 版本管理机制、Corepack 零开销调度器、pnpm 硬链接存储模型)。
### nvm 速查
```bash
brew install nvm
mkdir -p ~/nvm
```
在 `~/.zshrc` 中追加(完整脚本见子文档):
```bash
export NVM_DIR="$HOME/nvm"
[ -s "$(brew --prefix)/opt/nvm/nvm.sh" ] && . "$(brew --prefix)/opt/nvm/nvm.sh"
EOF
source ~/.zshrc
```
### pnpm
```bash
corepack enable
corepack prepare pnpm@latest --activate
```
详见子文档了解 Corepack 机制、pnpm workspace 与 store 管理。
### VS Code(推荐)
```bash
brew install --cask visual-studio-code
```
然后在 VS Code 中打开扩展面板,搜索并安装以下插件:
- ESLint
- Prettier
- TypeScript Debugger
## 四、TypeScript
```bash
npm install -g typescript
```
验证:
```bash
tsc -v # 如 v5.6.3
```
## 五、Go
详见 [[mac-dev-env-setup/go-module-proxy]](GOPROXY 代理链原理、GOSUMDB 校验机制、Go Workspace / vendor 模式)。
```bash
brew install go
go env -w GOPROXY=https://goproxy.cn,direct
```
验证:
```bash
go version # 如 go1.23.x
go env GOPROXY # 应输出:https://goproxy.cn,direct
```
### VS Code Go 插件
VS Code 扩展面板搜索安装 **Go**(by Gore-Multi),安装后会弹出提示是否安装 Go 工具链子组件,点 **Install All** 即可。
## 六、Python(按需)
如果所在组使用 Python 栈,提前装好:
```bash
brew install python@3.12
python3 -m pip install --upgrade pip
python3 -m venv ~/venvs/default
source ~/venvs/default/bin/activate
```
### uv(可选,更快的 Python 包管理器)
```bash
brew install uv
```
## 七、Java(按需)
```bash
brew install --cask temurin
# 或
brew install openjdk@17
```
在 `~/.zshrc` 中加入 JAVA_HOME:
```bash
export JAVA_HOME=$(/usr/libexec/java_home -v 17)
```
## 八、GitHub CLI
详见 [[mac-dev-env-setup/gh-cli-commands]](PR / Issue / Fork 常用命令与完整工作流)。
```bash
brew install gh
gh auth login # 按提示登录 GitHub 账号
gh --version # 验证
```
### 日常高频命令速查
| 操作 | 命令 |
|------|------|
| Clone 仓库 | `gh repo clone owner/repo` |
| Fork + 克隆 | `gh repo fork owner/repo` |
| Checkout PR | `gh pr checkout 12` |
| 创建 PR | `gh pr create --title "feat: xxx" --body "desc"` |
| 列出 Issues | `gh issue list --label bug` |
| 查看自己的 PR/Issue | `gh pr status` / `gh issue status` |
| 终端查看详情 | `gh pr view 42` / `gh issue view 42` |
> [!tip] gh + Claude Code 协作
> 先用 `gh issue list` 拉出任务,再让 Claude Code 在当前分支实现,比在浏览器切来切去高效得多。见 [[mac-dev-env-setup/ai-coding-agent]]。
## 九、AI Coding Agent — Claude Code
详见 [[mac-dev-env-setup/ai-coding-agent]](Prompting 四原则、CLAUDE.md 上下文注入、与 gh CLI 组合工作流)。
### 安装
```bash
npm install -g @anthropic-ai/claude-code
```
### 首次运行
```bash
claude
```
按提示登录 Anthropic 账号并配置 API Key。
> [!info] 让 Claude Code 调用 GitHub CLI
> Claude Code 可以原生理解仓库上下文,配合 `gh` 使用效果更好:先 `gh issue list` 查看任务,再让 Claude Code 直接在当前分支实现。
## 十、VS Code 常用插件汇总
| 插件名 | 用途 |
|--------|------|
| Go | Go 语言支持 |
| ESLint | JS/TS 代码检查 |
| Prettier | 代码格式化 |
| GitLens | Git 增强 |
| Error Lens | 行内错误提示 |
| Thunder Client | API 调试(替代 Postman) |
| Todo Tree | 自动收集 TODO/FIXME |
| Remote - SSH | SSH 远程开发 |
| Docker | Dockerfile / compose 支持 |
一键批量安装(保存为 `extensions.txt` 后运行 `code --install-extension $(cat extensions.txt)`):
```text
golang.go
dbaeumer.vscode-eslint
esbenp.prettier-vscode
eamodio.gitlens
bierner.markdown-preview-github-styles
mutantdino.resourcemonitor
```
## 关联笔记
- [[weekly/00-week-zero-prep-guide]] — 开营前预习指南(总览)
- [[mac-dev-env-setup/homebrew-intro]] — Homebrew 深度指南
- [[mac-dev-env-setup/git-ssh-config]] — Git & SSH 双账号路由与排障
- [[mac-dev-env-setup/node-nvm-pnpm]] — nvm / Corepack / pnpm 工作原理
- [[mac-dev-env-setup/go-module-proxy]] — Go Module 代理链与校验机制
- [[mac-dev-env-setup/gh-cli-commands]] — GitHub CLI 常用命令与工作流
- [[mac-dev-env-setup/ai-coding-agent]] — AI 编码提示词策略与安全边界
@@ -0,0 +1,163 @@
---
tags: [ai, claude-code, dev-env]
create time: 2026-07-01 00:00
---
# AI Coding Agent 用法指南
## 概述
在实训环境中使用 AI 辅助开发的规范化方法:Claude Code 作为首选 Coding Agent,配合 GitHub CLI 等工具形成闭环工作流。重点在于 **提示词工程、权限边界、上下文组织** 三要素。
## 核心概念
### Prompting 四原则
无论使用何种 AI 编码工具,以下原则通用:
| 原则 | 要点 | 反面示例 |
|------|------|---------|
| **具体** | 精确到文件名、行号、函数名 | "帮我优化一下登录页面" |
| **限定范围** | 明确说"只改什么",不说"改什么" | 无范围约束 → 过度改动 |
| **可验证** | 给出预期结果或验收标准 | "让它能跑就行" |
| **分步** | 复杂任务拆成小步骤逐步确认 | 一次性描述整个重构 |
### Claude Code 上下文注入机制
Claude Code 在启动后会自动收集以下上下文:
```
当前工作目录结构
├── CLAUDE.md ← 知识库/项目规范(固定注入)
├── .claude/settings.local.json ← 权限配置(可选)
├── .gitignore
├── src/ ← 当前打开/选中的文件
└── ...
```
| 注入方式 | 说明 |
|---------|------|
| **CLAUDE.md** | 项目级指令,Claude Code 启动时自动加载到 system prompt |
| **当前文件** | 你正在查看/编辑的文件自动加入 context |
| **选中文本** | 在编辑器选中后用 `@` 引用或直接在对话中使用 |
| **文件附件** | 用 `@file` 语法显式追加任意文件到上下文窗口 |
### CLAUDE.md 模板结构
```markdown
# Project Context
## 技术栈
- Go 1.23 + Gin, Node.js 20 + React 19
## 代码规范
- 错误处理必须 wrapping(fmt.Errorf("failed to X: %w", err))
- API handler 命名:HandlerSuffix(CreateUserHandler)
## 工作流约定
- PR 标题格式:type(scope): description(feat(auth): add login endpoint)
- 每个 commit 必须是 squash-friendly 的小粒度
```
## 代码示例
### 典型任务工作流
#### 场景 1:实现一个 API 接口
```
在 internal/handler/user.go 中增加 GetUserByID handler,
只改这一个文件,不要动其他代码。
要求:参数绑定使用 gin 的 query binding,错误码使用 pkg/errno 包定义的常量。
```
#### 场景 2:审查已有改动
```
审查刚才的改动(src/auth/middleware.ts),有没有潜在 bug 或性能问题。
重点关注:token 过期处理、中间件执行顺序、内存泄漏风险。
```
#### 场景 3:围绕 Issue 工作
```
查看 #42 issue 的描述,创建一个修复分支 fix-42-rate-limit,
实现限流逻辑后提交并创建 PR。PR 描述中包含复现步骤和修复说明。
```
### 与 GitHub CLI 组合使用
```bash
# Step 1:查看任务清单
gh issue list --state=open --label="internship"
# Step 2:让 Claude Code 直接在这个上下文中工作
# (在 Claude Code 中直接输入上述命令的输出或使用 @)
# Step 3:完成后再切回来发 PR
gh pr create --title "feat(limit): add rate limiter for signup API" \
--body "@@projects/rate-limiter-design.md"
```
## 常见陷阱与最佳实践
### 1. 上下文窗口溢出
Claude Code 的上下文窗口有限,当项目很大时不要一次性追加太多文件:
```
# ❌ 不好:把整个 src/ 文件夹丢进去
@src/*.go
# ✅ 好:只追加当前文件和相关接口定义
@internal/handler/user.go
@pkg/errno/code.go
```
需要跨文件理解时,先用 Grep 定位关键词再精准追加。
### 2. AI 生成代码不直接提交
AI 生成的代码可能存在 **隐蔽的逻辑错误或安全隐患**,务必经过人工审查:
```
审查流程:
1. 让 Claude Code 生成代码 → diff 输出
2. 人工阅读 diff,逐行检查
3. 如有问题,用自然语言指出("这里少了 nil check")→ 让其修正
4. 确认无误后再手动 staged + commit
```
> [!warning] 绝对不要做的事
> - 不要信任 AI 生成的数据库 migration SQL 不经 review 就执行
> - 不要 trust AI 生成的敏感信息(AK/SK、token)直接 commit
> - 不要在 prod 环境让 AI 直接操作
### 3. Prompt 太长反而降低质量
一个超过 500 字的 prompt 通常意味着意图不够聚焦。遵循 **STAR 原则**:
| 元素 | 说明 | 示例 |
|------|------|------|
| **S**ituation | 当前背景 | "我在写一个用户注册的 API handler" |
| **T**ask | 你要做什么 | "需要加上邮箱验证码校验" |
| **A**ction | 具体要求 | "用 Redis SETEX 做 1 分钟有效期,key 前缀 `code:email:`" |
| **R**esult | 期望输出 | "返回 Go struct 并在注释中标明 error code" |
### 4. 利用会话历史进行迭代
不要试图一次性完美。采用增量反馈循环:
```
第一轮:实现功能 → AI 出代码 → 我 review
第二轮:"这个实现有个问题,XX 没处理" → AI 修正
第三轮:"再加个单元测试" → AI 补测试
第四轮:"把错误处理改为 errors.Is 兼容风格" → AI 微调
```
每轮控制在 2-3 次交互内,超出就停下来自己总结。
## 延伸阅读
- [[mac-dev-env-setup/homebrew-intro]] — Claude Code 安装前置(npm/nvm 环境)
- [[CLAUDE.md]] — 本笔记库的 CLAUDE.md 本身就是一个实战范例
@@ -0,0 +1,136 @@
---
tags: [github, cli, dev-env]
create time: 2026-07-01 00:00
---
# GitHub CLI (gh) 命令速查
## 概述
`gh` 是 GitHub 官方 CLI,在终端完成 PR、Issue、Fork、Clone 等操作,比浏览器更流畅。它与 Git + Claude Code 组合可以形成完整的高效开发工作流。
## 安装
```bash
# macOS
brew install gh
# 验证
gh --version
gh auth login # 首次运行,按提示登录 GitHub 账号
```
## Pull Request 操作
### 查看与筛选
```bash
gh pr list # 当前仓库的 open PR(最近 30 条)
gh pr list --state closed # 已关闭的 PR
gh pr list --assignee your-user # 分配给自己的 PR
gh pr status # 自己相关的 PR:当前分支 / 创建过 / 需要你 review
```
### Checkout 到本地
```bash
gh pr checkout 12 # 通过 PR 编号 checkout(自动处理 fork)
gh pr checkout patch-2 # 通过分支名 checkout
gh pr view 12 # 终端内查看 PR 详情
gh pr view 12 --web # 浏览器打开 PR
```
### 创建 PR
```bash
gh pr create # 交互式创建
gh pr create --title "feat: add xxx" --body "description"
gh pr create --web # 浏览器打开创建页
```
## Issue 操作
```bash
gh issue list # 列出 open issues
gh issue list --label bug # 按标签过滤
gh issue list --assignee user # 按负责人过滤
gh issue status # 与你相关的 issues(分配/提及/自己开的)
gh issue view 42 # 终端查看 issue 详情
gh issue view 42 --web # 浏览器打开
gh issue create # 交互式创建
gh issue create --label bug --title "fix: xxx"
```
## Repository 操作
### Clone
```bash
gh repo clone owner/repo # OWNER/REPO 语法
gh repo clone https://github.com/owner/repo # URL 语法
```
### Fork
```bash
# 在已有仓库目录中
gh repo fork # 自动 fork + 询问是否添加 remote
# 跳过 remote 提示
gh repo fork --remote=false
# Fork 后跳过克隆
gh repo fork owner/repo --clone=false
# Fork 时直接克隆
gh repo fork owner/repo # 会自动问是否 clone
```
### View
```bash
gh repo view owner/repo # 终端查看仓库信息 + README
gh repo view owner/repo --web # 浏览器打开
gh repo view # 当前所在仓库
```
## 常见工作流示例
### Fork → 开发 → 提 PR
```bash
gh repo fork owner/repo # 1. Fork
cd repo # 进入目录
git checkout -b feature/new-ui # 2. 创建功能分支
# ... 编码 ...
git commit -m "feat: new ui"
git push origin feature/new-ui # 3. 推送
gh pr create --title "feat: new UI components" \
--body "Closes #42" # 4. 创建 PR
```
### Review 别人提交的 PR
```bash
gh pr checkout 8896 # 1. Checkout 别人的 PR
git pull origin patch-2 # 确保最新
# ... 审查代码 ...
```
### Claude Code + gh 协作
```bash
gh issue list # 1. 查看任务列表
gh issue view 42 # 查看具体需求
claude # 2. AI 助手直接在当前分支实现
```
## 参考链接
- GitHub 官方文档: <https://cli.github.com/>
- [[mac-dev-env-setup]] — macOS 开发环境配置总指南
- [[mac-dev-env-setup/ai-coding-agent]] — AI Coding Agent 安全边界与提示策略
@@ -0,0 +1,128 @@
---
tags: [git, ssh, dev-env]
create time: 2026-07-01 00:00
---
# Git & SSH 配置
## 概述
Git 本地配置、SSH Key 管理与多账户/多主机路由,确保 GitHub 与私有 Gitea 实例能同时免密协作。核心在于 `~/.ssh/config` 文件将不同主机映射到独立的私钥。
## 核心概念
### Git 全局配置项速览
```bash
git config --global user.name "hezhaohui"
git config --global user.email "hezhaohui0807@163.com"
git config --global core.autocrlf input # 写时转 LF,避免 Windows CRLF 混入仓库
git config --global init.defaultBranch main # 初始化用 main(不再过时默认的 master)
git config --global init.forcedCloneProtocol https # git clone 默认走 HTTPS(可选)
```
> [!info] 查看 / 删除配置
> - `git config --global --list` — 列出所有全局设置
> - `git config --global --unset user.name` — 删除某项
> - `git config --edit --global` — 直接编辑 `~/.gitconfig`
### SSH Key 为什么需要独立密钥对
同一个 GitHub / Gitea 账号如果共用一个 SSH Key 是可以的,但 **按服务分 key** 有以下好处:
| 优势 | 说明 |
|------|------|
| 隔离风险 | Gitea 服务器如果泄露某个部署密钥(deploy key),不会牵连你的 GitHub 主身份 |
| 审计清晰 | 服务端日志中 `Host A uses id_ed25519_github` vs `id_ed25519_gitea`,一眼区分来源 |
| 灵活轮换 | 替换 Gitea 密钥不影响 GitHub 已授权的 session |
### ~/.ssh/config 路由机制
SSH 客户端在发起连接时会顺序读取 `~/.ssh/config`,**第一个匹配规则生效**。关键指令:
| 指令 | 作用 |
|------|------|
| `Host` | 别名(不是真实主机名),匹配 `.git@remote-url` 中的 hostname 部分 |
| `HostName` | 真实 DNS 名或 IP |
| `Port` | SSH 端口(默认 22) |
| `User` | SSH 认证用户名 |
| `IdentityFile` | 使用的私钥路径 |
| `IdentitiesOnly yes` | 强制只使用指定 key,不尝试系统其他 key |
示例完整配置:
```ssh-config
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_github
IdentitiesOnly yes
Host gitea-self
HostName 47.121.181.112
Port 3000
User git
IdentityFile ~/.ssh/id_ed25519_gitea
IdentitiesOnly yes
```
连接测试验证:
```bash
ssh -T git@github.com # Hi hezhaohui! You've successfully authenticated...
ssh -T git@gitea-self # logged in as hezhaohui
```
> [!tip] verbose 调试
> 遇到 "Permission denied" 时加 `-v` 打印详细握手日志:
> ```bash
> ssh -Tv git@github.com 2>&1 | grep "Offering"
> # 看客户端主动发送了哪个 key、服务端拒绝了哪一个
> ```
## 常见陷阱与最佳实践
### 1. SSH Config Host 别名必须与实际 URL 一致
```bash
# ❌ 错误:.git 远端仍指向原始地址
git remote add origin git@47.121.181.112:3000/user/repo.git
# ✅ 正确:使用 alias,让 config 中的 Host 匹配
git remote add origin git@gitea-self:3000/user/repo.git
```
Git 克隆时的远程 URL 格式为 `git@[Host]:path`,`Host` 必须和 `~/.ssh/config` 里的 `Host` 完全一致才会命中对应的 IdentityFile 规则。
### 2. Git 的 HTTP 代理干扰 SSH
如果你设置了 `http.proxy` 或 `https.proxy`,某些工具链可能影响 `ssh` 命令的网络行为。对于 SSH 专用代理(如 proxychains),要排除内网地址:
```bash
# .gitconfig 中排除 Gitea 内网段
[url "ssh://git@gitea-self:3000/"]
insteadOf = ssh://git@47.121.181.112:3000/
```
### 3. 私钥权限过松导致被拒绝
```bash
chmod 600 ~/.ssh/id_ed25519_gitea
chmod 600 ~/.ssh/config # SSH client 也要求 config 不能开放可读
```
OpenSSH 如果检测到私钥文件对其他用户可读写,会直接忽略它——这是最常见的新手踩坑。
### 4. Ed25519 vs RSA:优先用 Ed25519
| 算法 | 公钥长度 | 私钥长度 | 安全性 | 速度 |
|------|---------|---------|--------|------|
| **Ed25519** ✅ | 68 bytes | 68 bytes | 高 | 快 |
| RSA 4096 | 968 bytes | ~3 KB | 中高 | 慢 |
Ed25519 不受 Heartbleed 类漏洞影响,且密钥更小、签名更快。除非服务端明确限制(极老设备),否则一律用 ed25519。
## 延伸阅读
- [[mac-dev-env-setup/homebrew-intro]] — Homebrew 包管理器安装 Git
- [[mac-dev-env-setup/node-nvm-pnpm]] — Node.js 环境搭建(后续依赖)
@@ -0,0 +1,190 @@
---
tags: [go, module, proxy, dev-env]
create time: 2026-07-01 00:00
---
# Go Module 代理与依赖管理
## 概述
Go Modules 是 Go 自 v1.11 引入的官方依赖管理方案,GOPROXY 环境变量决定了模块下载的来源。国内用户通过配置代理加速拉取,本文深入 Module 体系与代理机制。
## 核心概念
### GOPROXY 的工作原理
```
go get ./...
│
▼
GOPROXY 列表依次查询 → 命中第一个返回
│ (类似 DNS 回退链)
▼
缓存到 ~/go/pkg/mod/cache/
│
▼
写入 go.sum(校验哈希)
```
```bash
# 默认值(中国大陆不可达)
go env GOFLAGS # 应设为空或不设
# 推荐:阿里 + goproxy.io 备用
go env -w GOPROXY=https://goproxy.cn,direct
# 也可以指定多个(逗号分隔,从左到右优先级递减)
go env -w GOPROXY=https://mirrors.aliyun.com/goproxy/,https://goproxy.io,direct
```
为什么需要 `direct` 作为兜底?当模块是私有仓库、不在任何公开代理上时,`direct` 告诉 Go 直接通过 VCS(git/svn/hg)从源码仓库拉取。
### GOSUMDB 校验链
每个 `go.mod` 旁边都会有一个 `go.sum`,它记录了所有直接和间接依赖的 **模块版本 + 哈希**:
```bash
# 当前 GOSUMDB 设置
go env GOSUMDB # sum.golang.org(Google 托管的全球信任根)
# 离线模式(跳过哈希校验,开发阶段方便但不建议用于 CI)
go env -w GONOSUMCHECK=* # 跳过校验
go env -w GONOSUMDB=* # 不向 sumdb 请求
go env -w GOSUM=off # 完全关闭 sum 检查
```
> [!warning] GONOSUMCHECK vs GONOSUMDB vs GOSUM=off
> | 变量 | 效果 | 适用场景 |
> |------|------|---------|
> | `GONOSUMCHECK=*` | 跳过对 `go.sum` 比对,但仍查询 GOSUMDB | 不推荐使用 |
> | `GONOSUMDB=*` | 不向 sum.golang.org 查询,但仍做 local checksum | 自建镜像时使用 |
> | `GOSUM=off` | 完全禁用 hash 校验 | 仅限纯本地实验项目 |
生产环境务必保留 `GOSUMDB=sum.golang.org`,否则无法防御依赖供应链攻击(比如有人往公共 repo 推送恶意版本)。
### Go Workspace(Go 1.18+)
当你在本地同时修改多个内部模块时,Go Workspace 可以绕过 GOPROXY,用本地路径解析替代网络下载:
```bash
# 初始化 workspace
go work init ./cmd/server ./internal/lib
# 添加已有模块
go work use ./pkg/utils
# 生成的 go.work 文件
cat go.work
# go 1.22
#
# use (
# ./cmd/server
# ./internal/lib
# ./pkg/utils
# )
```
Workspace 模式下,`go build` / `go test` 会优先使用 `use` 列表中本地路径对应的模块版本,而非 `GOPROXY` 下载的缓存版本。这在做 monorepo 或多模块协同开发时非常有用。
### vendor 模式:离线构建
```bash
# 将所有依赖下载到本地 vendor/ 目录
go mod vendor
# 用 vendor 目录构建(完全离线)
go build -mod=vendor ./...
```
`vendor/` 会被纳入代码仓库并提交,这样新成员 clone 后即使没有网络也能编译。对比:
| 方式 | 是否需要网络 | 是否提交 | 适用场景 |
|------|-------------|---------|---------|
| **Module cache** | 首次需要 | 否(本地磁盘) | 日常开发 |
| **vendor/** | 不需要 | 是 | CI/CD、内网隔离 |
| **Go Workspace** | 不需要 | 是(go.work) | 多模块本地协同 |
## 代码示例
### 批量检查过期依赖
```bash
# 使用 depaware 第三方工具可视化依赖关系并发现重复模块
go install github.com/tailscale/depaware@latest
depaware --print ./...
```
### 清理未使用的依赖
```bash
# 移除 go.mod 中不再需要的 require 条目
go mod tidy
# 清理本地 module cache 中无人引用的旧版本
go clean -modcache # ⚠️ 谨慎使用:会删掉整个 ~/go/pkg/mod/cache
```
`go mod tidy` 的核心逻辑:扫描 `*.go` 文件的 import 路径 → 去 `go.mod` 中查找对应 require → 未被导入且无 build tag 使用的条目会被自动删除,新增的导入会自动添加。
## 常见陷阱与最佳实践
### 1. GOPROXY 配错导致 "bad response"
当代理地址不可达时,Go 会报 403/404/502。排查步骤:
```bash
# 第一步:手动 curl 测试代理健康度
curl -i https://goproxy.cn/github.com/aws/aws-sdk-go/@v/v1.45.0.zipinfo
# 期望:HTTP 200 + 响应体包含 {"Path":"github.com/aws/aws-sdk-go", ...}
# 失败:检查代理 URL 是否正确、是否有防火墙拦截
```
阿里云的 `https://mirrors.aliyun.com/goproxy/` 在某些地区更稳定,可切换测试。
### 2. go.sum 丢失或不同步
`go.sum` 不应手动编辑。如果不小心修改了导致冲突:
```bash
# 重建 go.sum(基于 go.mod + 当前可用 GOPROXY 重新拉取)
rm go.sum
go mod download
go mod verify # 确认每个依赖的哈希都匹配
```
### 3. 私有仓库需要结合 GOPRIVATE
```bash
# 跳过代理和 sumdb 校验,走 VCS 直接拉取
go env -w GOPRIVATE=git.internal.company.com/*
```
> [!tip] GOPRIVATE 与 GOPROXY 的关系
> `GOPRIVATE` 模块不走 GOPROXY,也触发 GONOSUMCHECK/GONOSUMDB。如果你只想屏蔽特定域名而不全部关闭校验,可以:
> ```bash
> go env -w GOPRIVATE=git.internal.company.com
> # GOPROXY 仍然走 goproxy.cn,只有匹配的域名例外
> ```
### 4. Module 语义化版本陷阱
Go Modules 使用 [Semantic Import Versioning](https://github.com/golang/go/wiki/Modules#semantic-import-versioning):如果一个模块 v2+ 发生了 breaking change,它的 import path 应带上 `/v2` 后缀:
```
# v1.x → import "example.com/foo"
# v2.x → import "example.com/foo/v2"
```
很多开源库(如 `gin-gonic/gin`)忽略了这一约定,直接用 `v2.x` 但没有在 import path 上加 `/v2`。这时需要在 `go.mod` 里显式声明:
```go
require github.com/example/broken-module v2.3.4 // indirect
// 或用 replace 纠正
replace github.com/example/broken-module v2.3.4 => github.com/example/broken-module v2.3.4
```
## 延伸阅读
- [[mac-dev-env-setup/homebrew-intro]] — 通过 Homebrew 安装 Go
- [[mac-dev-env-setup/git-ssh-config]] — 私有仓库需先配置 SSH Key
@@ -0,0 +1,221 @@
---
tags: [homebrew, macos, package-manager]
create time: 2026-07-01 00:00
---
# Homebrew — macOS 包管理器
## 概述
Homebrew(简称 brew)是 macOS 上最流行的开源包管理工具,弥补了 macOS 缺乏官方包管理器的空白。它通过命令行安装、更新和卸载 Unix 工具和桌面应用,是 Mac 开发环境搭建的第一步。
## 核心概念
### 目录结构
```
/opt/homebrew/ # ARM Mac 安装根目录(M1/M2/M3/M4)
├── bin/ # 可执行文件(brew 本身在此)
├── Cellar/ # 已安装包的实际存放位置(版本化目录)
├── Cask/ # GUI 应用(--cask)的安装元数据
├── etc/ # 配置文件
├── include/ # C/C++ 头文件
├── lib/ # 动态链接库
├── opt/ # 当前活跃版本的 symlink 目标
├── share/ # 共享资源(man pages, completions 等)
└── var/ # 运行时数据
/usr/local/ # Intel Mac 安装根目录
```
> [!info] Cellar vs Opt
> `Cellar/<formula>/<version>` 存储每个版本的实际文件;`opt/<formula>` 是一个 symlink,始终指向当前最新版本。这就是 `brew upgrade` 后不需要重新配置 PATH 的原因。
### Formula vs Cask
| 类型 | 用途 | 示例 | 安装路径 |
|------|------|------|----------|
| **Formula** | CLI 工具和库 | `git`, `go`, `python@3.12` | `/opt/homebrew/Cellar/...` |
| **Cask** | GUI 桌面应用 | `visual-studio-code`, `iterm2` | `/Applications/` |
```bash
# Formula 安装
brew install git
# Cask 安装(注意 --cask 或直接用 install,brew v4+ 自动识别)
brew install --cask visual-studio-code
```
### Tap —— 第三方仓库
默认只包含 Homebrew 官方的 core tap(formula + cask)。社区维护的第三方仓库称为 **tap**。
```bash
# 查看已添加的 taps
brew taps
# 添加社区 tap
brew tap homebrew/cask-fonts # 字体 cask
brew tap darwinports # 假设的第三方 tap
# 从 tap 安装
brew install darwinports/my-tool
```
> [!tip] 常见社区 tap
> - `homebrew/cask-fonts` — 大量字体应用
> - `homebrew/core` 和 `homebrew/cask` 默认已添加
> - 添加前用 `brew search <name>` 确认是否在官方源中,避免不必要的 tap
## 代码示例
### 安装与初始化
```bash
# 一键安装脚本
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# ARM Mac:将 brew 加入 shell profile
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile
eval "$(/opt/homebrew/bin/brew shellenv)"
# Intel Mac
echo 'export PATH="/usr/local/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc
```
`brew shellenv` 会输出需要注入到 shell 中的环境变量(PATH、MANPATH、CGO_CFLAGS 等),`eval` 将其应用到当前环境。
### 常用工作流
```bash
# 搜索包(formula + cask)
brew search neovim
# 查看详情(版本、依赖、安装数)
brew info neovim
# 安装
brew install neovim
# 指定版本(需先用 brew versions 或查 formula history)
brew install neovim@0.9
# 升级
brew upgrade # 升级所有可升级的包
brew upgrade neovim # 只升级某个包
# 清理磁盘空间
brew cleanup # 删除旧版本缓存
brew cleanup --prune # 同时清理孤立 symlink
# 诊断
brew doctor # 检查环境问题
brew config # 查看当前配置信息
```
### 管理依赖
```bash
# 查看某包的依赖树
brew deps --tree git
# 查看哪些包依赖某包(反向查询)
brew depends --tag python@3.12
# 列出已安装的包
brew list
# 列出可卸载的孤立依赖(无人引用)
brew autoremove
```
> [!warning] autoremove 不会删除你显式安装的包
> 只有那些因满足其他包的依赖而被自动安装、且当前不再被任何包需要的依赖才会被移除。
### 源码编译自定义参数
```bash
# 查看可用选项
brew options curl
# 安装时启用特定 flag
brew install curl --with-openssl
# 或者编辑 formula 后再安装(bottle 会被跳过)
brew edit curl # 打开本地 formula 副本
brew install curl
```
`brew edit <formula>` 会在本地创建一个公式副本,适合临时修改编译参数,但升级时会提示冲突。
## 常见陷阱与最佳实践
### 1. PATH 优先级问题
macOS 系统自带的工具(如 `/usr/bin/python3`)可能比 brew 安装的更早出现在 PATH 中。确保 brew 路径在 `/usr/local/bin` 或 `/opt/homebrew/bin` 之前:
```bash
echo $PATH
# 期望顺序:/opt/homebrew/bin:...(在 /usr/bin 之前)
```
> [!tip] 验证方法
> 运行 `which git` 应输出 `/opt/homebrew/bin/git`(ARM)或 `/usr/local/bin/git`(Intel),而非 `/usr/bin/git`。
### 2. Permission Denied 不要用 sudo
```bash
# ❌ 错误做法
sudo brew install git # 会破坏 ownership,导致后续操作全部报错
# ✅ 正确做法
chown -R $(whoami) $(brew --prefix)/* # 修复权限后重试
```
brew 设计的初衷就是用户级别使用,使用 `sudo` 会改变 `/opt/homebrew` 下文件的 owner,引发连锁问题。如果误用了 `sudo brew`,用上面的命令修复即可。
### 3. 大版本升级后的迁移
```bash
# Homebrew v4 (2023+) 要求先运行迁移命令
brew update
brew doctor # 检查是否需要迁移
brew bump-formula-pr --arch ... # 通常无需手动干预
```
### 4. 离线环境 / 国内网络优化
中国大陆用户安装和下载可能较慢,可以通过设置镜像源加速:
```bash
# Git 仓库镜像(可选,通常无需设置,brew 官方源在国内访问正常)
# 替换为清华大学镜像
git -C "$(brew --repo)" remote set-url origin https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/brew.git
# pip / npm 等有专门的镜像配置方式,这里不展开
```
### 5. Bottle vs Build from Source
brew 默认优先下载预编译的 **bottle**(二进制包),速度远快于从源码编译。某些特殊架构或定制需求时才需要从源码构建:
```bash
# 强制从源码编译(跳过 bottle)
brew install --build-from-source curl
```
### 6. 公式维护约定
brew formula 采用 "one version at a time" 策略——`brew install git` 只装最新稳定版,不保留历史版本。如果需要多版本共存(类似 nvm for Node),推荐:
- Go → 用 `gvm` 或通过 golang.org/dl 官网安装
- Python → `pyenv` 配合 `brew install pyenv`
- Node.js → `nvm`(已在本环境的 Node 章节覆盖)
## 延伸阅读
- [Homebrew 官方文档](https://docs.brew.sh)
- [[projects/mac-dev-env-setup]] — macOS 开发环境总指南
- [[technical/go]] — Go 语言环境配置
- [[technical/nodejs]] — Node.js 与 pnpm 配置
@@ -0,0 +1,208 @@
---
tags: [nodejs, nvm, pnpm, dev-env]
create time: 2026-07-01 00:00
---
# Node.js + nvm + pnpm 详解
## 概述
Node.js 开发环境中版本管理和包管理的核心链路:nvm 控制运行时版本、Corepack 提供标准化的包管理器入口、pnpm 以高效磁盘模型取代传统的 flat install。三者配合形成完整的 JS/TS 工程基础。
## 核心概念
### nvm 版本管理机制
nvm(Node Version Manager)的核心设计是通过 shell 函数劫持 `node` / `npm` / `npx` 命令:
```bash
# nvm 工作原理示意
which node
# → $(nvm_alias)/versions/node/*/bin/node ← 实际是符号链接
# ↑ 由 nvm 动态切换
```
| 操作 | 命令 | 说明 |
|------|------|------|
| 安装 LTS | `nvm install --lts` | 自动检测最新 Long Term Support 版本 |
| 切换版本 | `nvm use <version>` | 修改 `.nvmrc` 或版本号 |
| 查看已装 | `nvm ls` | 列出版本树 |
| 设置默认 | `nvm alias default 20` | 每次打开终端自动激活 |
| 全局包复用 | `--reinstall-packages-from=<version>` | 切换时迁移全局包 |
```bash
# 在项目根目录创建 .nvmrc
echo "20" > .nvmrc
# nvm use 不加版本号时自动读 .nvmrc
cd my-project && nvm use
# → Found '/path/to/my-project/.nvmrc' with version <20>
# → Now using Node.js v20.18.0
```
> [!tip] nvm 与 corepack 的交互
> `corepack prepare pnpm@latest --activate` 安装的是 `corepack` 自己,nvm 切换 Node 版本后,corepack 依然存在——因为它是随 Node.js bundled 的(Node ≥ 16.13)。这意味着 **不需要** 在切换 Node 版本后重新安装 corepack。
### Corepack 的作用
Corepack 是 Node.js 官方提供的零开销包管理器调度器,从 Node v16.13 起内置:
```bash
# Corepack 支持的包管理器
corepack enable # 注册 pnpm / yarn / npm 的 shim 入口
corepack prepare pnpm@latest --activate # 锁定 pnpm 版本
# 查看 corepack 管理的版本
corepack --version
corepack --enable
```
核心思想:**让团队统一使用包管理器版本,而非各自在全局安装不同版本的 npm/yarn/pnpm。**
```bash
# 项目中可指定 pnpm 版本
echo "pnpm@8.15.0" > .npmrc # Corepack 读取
# 或直接通过 package.json
# (package.json 中添加 "packageManager": "pnpm@8.15.0")
```
CI 跑 `corepack enable` 即可自动下载指定版本,无需额外安装步骤。
### pnpm 的存储模型
pnpm 最核心的创新在于 **硬链接 + 内容寻址存储**,解决了 npm/yarn 的两个经典问题:
1. **磁盘浪费**:npm 在每个 node_modules 下复制依赖副本
2. **隐形依赖**:flat tree 结构中子包能意外访问父包的依赖
```
传统 npm 安装(flat tree,symlink 树)
project-A/node_modules/
├── lodash/ ← symlink -> project-A/node_modules/lodash
├── express/ ← symlink -> project-A/node_modules/express
│ └── node_modules/
│ └── qs/ ← 可能被 project-B 重复安装
pnpm 安装(strict 模式)
pnpm-store/
├── .stores/v8/
│ └── abc123/ ← 内容哈希索引,全局唯一
│ ├── lodash.tgz
│ └── express.tgz
project-A/node_modules/
├── lodash/ ← hard link (硬链接) → .stores/v8/abc123/lodash.tgz
├── express/ ← hard link → .stores/v8/abc123/express.tgz
└── .pnpm/
└── express@4.x/ ← nested symlink 满足 express 自身的 require('qs')
```
**硬链接的优势**:同样的文件在磁盘上只存一份,`node_modules` 中的硬链接不占用额外空间;而 symlink 在 Windows 上需要管理员权限才能创建。
> [!warning] Windows 上的 pnpm
> Windows 10+ 支持硬链接,但默认可能需要开启"开发者模式"。如果遇到 permission denied,以管理员身份运行终端,或在系统设置中启用开发者模式。
### pnpm workspace(Monorepo 支持)
```json
{
"name": "my-monorepo",
"private": true,
"workspaces": ["packages/*"]
}
```
workspace 模式下,同仓库内的包互相引用时直接使用硬链接,无需 publish:
```bash
cd packages/shared && pnpm add ../libs/core
# 等价于在 shared 的 package.json 中写了 "core": "link:../libs/core"
```
## 代码示例
### 项目级 .npmrc 推荐配置
```ini
# .npmrc
auto-install-peers=true
side-effects-cache=true # 缓存 noSideEffects=true 的包,加快安装
shamefully-hoist=false # 禁止非 hoist 提升到顶层
strict-peer-dependencies=true # peerDependency 缺失时报错而非警告
```
### 快速诊断 node_modules 大小
```bash
# macOS/Linux
du -sh node_modules/
# 找出最大的前 10 个包
pnpm why --recursive | head -20
```
## 常见陷阱与最佳实践
### 1. nvm 与 Node.js 全局 CLI 丢失
切换 Node 版本后,之前在全局安装的 CLI 工具(如 `typescript`、`eslint`)不再可用,因为每个 Node 版本有独立的全局目录:
```bash
# 切换时保留全局包(仅同大版本间安全)
nvm use 20 --reinstall-packages-from=18
# 或者通用做法:CLI 工具放在工作区 root 的 devDependencies 中
pnpm add -D typescript eslint
npx tsc --version # 始终能用
```
> [!tip] 黄金法则:CLI 工具不进 global,进 devDependencies
> 所有团队工具的版本应该锁在 `package.json` 中,通过 `npx <tool>` 调用。这是避免"我的能跑你不行"问题的最根本策略。
### 2. Corepack 版本冲突
如果你的团队中有成员安装了独立的全局 pnpm,会与 Corepack 冲突:
```bash
# 检查当前 pnpm 来源
which pnpm
# → 应该是:$(corepack_dir)/pnpm → .corepack/pnpm → 目标二进制
# 卸载独立安装的全局 pnpm
npm uninstall -g pnpm
# 重新用 corepack 激活
corepack enable
corepack prepare pnpm@latest --activate
```
### 3. pnpm store 膨胀
pnpm 的内容寻址存储在反复安装/删除不同版本后会产生碎片:
```bash
# 清理未被任何 package.json 引用过的 store 条目
pnpm store prune
# 定期检查 store 大小
du -sh $(pnpm store path)
```
建议每月执行一次 `pnpm store prune`,通常能释放数 GB 空间。
### 4. pnpm 与 Native Addon
带有 C++ 原生编译绑定的包(如 `sharp`、`bcrypt`)在 pnpm 环境下有时会因为找不到头文件路径而编译失败:
```bash
# 临时关闭 strict-deps 解决 header 路径问题
pnpm install --strict-peer-dependencies=false
# 长期方案:在 package.json 中声明正确的 dependencies 层级
```
## 延伸阅读
- [[mac-dev-env-setup/homebrew-intro]] — 通过 Homebrew 安装 nvm
- [[mac-dev-env-setup/git-ssh-config]] — SSH 配置(用于 git clone private repos)
- [[mac-dev-env-setup/go-module-proxy]] — Go 生态的依赖管理对比参考
+63
View File
@@ -0,0 +1,63 @@
---
tags: [onboarding, week-zero]
create time: 2026-07-01 00:00
---
# 第零周 · 开营前预习指南
## 概述
七牛云暑期实习 MS0(开营前)准备清单,涵盖账号与协作基础、开发环境、AI Coding Agent 三大模块,确保开营第一天即可直接上手项目,而非从零摸索工具。
## 一、账号与协作基础
### GitHub 账号
- 注册 GitHub 账号,提交 ID 并填写表单:<https://wj.qq.com/s2/27190567/04b8/>
- 收到邀约通知后,加入实训营 GitHub 组织
- 配置 SSH key,确保本地能免密 push
- ~~验收✅~~ 完成状态待定
> [!info] 备注
> Git 操作、commit 规范、PR、Fork 同步等协作流程开营后在真实项目中实践,不作开营前强制要求。
## 二、开发环境
配置时机:入职当天发放办公电脑,届时安装;希望提前熟悉也可先在个人电脑上试装。详细步骤见 [[technical/mac-dev-env-setup]](含 Homebrew → Git → Node/Go/AI Agent 完整指南)。
### Node.js
- 用 nvm 管理版本,安装一个 LTS 版本
- 包管理器用 pnpm
- 验证:`node -v`、`pnpm -v` 正常输出
### TypeScript
- 安装 TypeScript
- 验证:`tsc -v` 正常输出
### Go
- 安装 Go,配置 GOPROXY 国内代理加速依赖拉取([goproxy.cn](https://goproxy.cn/))
- 验证:`go version`、`go env GOPROXY` 正常
### 其他
- 代码编辑器(推荐 VS Code)及常用插件
- 终端与 Git
## 三、AI Coding Agent
实训允许并鼓励使用 AI 辅助开发,但 AI 服务于工程流程,不绕开设计、Review 和测试。
### 基本用法
- 安装并跑通一个 Coding Agent(如 Claude Code、Codex 等)
- 熟悉:基于明确任务下发指令、限定改动范围、阅读并检查生成结果
- 配置 GitHub CLI,使 Agent 能围绕 Issue / PR 工作(查看 Issue、创建分支、提交 PR、补充 PR 描述)
## 四、打卡清单
逐项确认完成情况:
- [ ] GitHub 账号已注册并加入组织,SSH key 配置完成(✅ 表单已提交,待邀约)
- [ ] Node(nvm + pnpm)配置完成并验证
- [ ] Go(GOPROXY)配置完成并验证
- [ ] 跑通至少一个 Coding Agent,配置好 GitHub CLI
## 关联笔记
- [[technical/mac-dev-env-setup]] — macOS 开发环境详细配置指南