其他
编写 Go 条件、循环和 switch…
在 Go 中编写 if、for、range、switch、type switch 和空标识符模式时,按官方惯用法组织控制流并避免作用域与分支陷阱。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 48/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 85/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 53/100 ×0.15
适用场景
编写 Go 条件、循环和 switch 通用
解决思路
- 资源路由:使用 switch、type switch、fallthrough 或 labeled break 时,读取 references/SWITCH-PATTERNS.md。
- 资源路由:使用 `_`、blank import、未使用的编译期断言或有意丢弃时,读取 references/BLANK-IDENTIFIER.md。
- if 初始化:`if` 和 `switch` 都接受可选初始化语句,用它把变量作用域限制在条件块内,例如 `if err := file.Chmod(0664); err != nil { log.Print(err); return err }`。
- 如果 `if` 之后几行仍需要该变量,单独声明变量并使用普通 `if`,例如 `x, err := f(); if err != nil { return err }`,后面继续使用 `x`。
- 缩进错误流(guard clause):当 `if` 体以 `break`、`continue`、`goto` 或 `return` 结束时,省略不必要的 `else`,保持成功路径不缩进。
- 当 `if` 已经 `return` 时,不要把正常流程埋进 `else`。
- 重声明与重赋值:`:=` 短声明允许在相同作用域中重声明变量,例如 `f, err := os.Open(name)` 声明 `f` 和 `err`,`d, err := f.Stat()` 声明 `d` 并重赋值 `err`。
- 变量 `v` 即使已经声明,也可以出现在 `:=` 声明中,条件为:声明与现有 `v` 在同一作用域;值可赋给 `v`;该声明至少新建一个其他变量。
- 变量遮蔽警告:如果 `v` 声明在外层作用域,`:=` 会创建新变量并遮蔽它,这是常见 bug;例如 `if *shortenDeadlines { ctx, cancel := context.WithTimeout(ctx, 3*time.Second); defer cancel() }` 内层 `ctx` 遮蔽外层 `ctx`,外层 `ctx` 不变。
- 遮蔽修复:如果本意是给外层变量重新赋值,用 `=` 而不是 `:=`,例如 `var cancel func(); ctx, cancel = context.WithTimeout(ctx, 3*time.Second)`。
- for 循环:Go 的 `for` 是唯一循环构造,统一 `while`、`do-while` 和 C 风格 `for`。
- 条件型 for(Go 的 while):`for x > 0 { x = process(x) }`。
- 无限循环:`for { if done() { break } }`。
- C 风格三组件 for:`for i := 0; i < n; i++ { ... }`。
- range:用 `range` 遍历 slice、map、string 和 channel。
- slice:`for i, v := range slice { ... }` 得到索引 + 值。
- map:`for k, v := range myMap { ... }` 得到键 + 值,顺序不确定。
- string:`for i, r := range "héllo" { ... }` 得到字节索引 + rune,不是 byte。
- channel:`for v := range ch { ... }` 接收直到 channel 关闭。
- range string 关键规则:产生 rune 而不是 byte;`i` 是字节偏移。
- range map 关键规则:顺序非确定性,不要依赖它。
- 用 `_` 丢弃索引或值:`for _, v := range slice`。
- 并行赋值:Go 没有逗号运算符;用并行赋值处理多个循环变量,例如 `for i, j := 0, len(a)-1; i < j; i, j = i+1, j-1 { a[i], a[j] = a[j], a[i] }`。
- `++` 和 `--` 是语句不是表达式,不能出现在并行赋值中。
- switch 的 labeled break:`switch` 位于 `for` 内时,`break` 只跳出 `switch`;用带标签的 `break` 跳出外层循环,例如 `Loop: for _, v := range items { switch v.Type { case "done": break Loop } }`。
- 类型 switch:见 go-interfaces 的 Type Switch。
- 空标识符:绝不要随意丢弃错误,否则后续可能发生 nil dereference panic。
- 编译期接口断言:路由到 go-interfaces。
- Quick Reference:If initialization 使用 `if err := f(); err != nil { }`。
- Quick Reference:Early return,当 `if` 体 `return` 时省略 `else`。
- Quick Reference:Redeclaration,同一作用域且有新变量时,`:=` 会重新赋值。
- Quick Reference:Shadowing trap,内层作用域 `:=` 会创建新变量。
- Quick Reference:Parallel assignment 使用 `i, j = i+1, j-1`。
- Quick Reference:Expression-less switch 使用 `switch { case cond: }`。
- Quick Reference:Comma cases 使用 `case 'a', 'b', 'c':`。
- Quick Reference:No fallthrough 是默认行为;需要时显式写 `fallthrough`。
- Quick Reference:从 switch 内的循环跳出使用 `break Label`。
- Quick Reference:丢弃值使用 `_, err := f()`。
- Quick Reference:副作用导入使用 `import _ "pkg"`。
- Quick Reference:接口检查路由到 go-interfaces。
- 相关技能:结构化 guard clauses、early returns 或 error-first patterns 时,见 go-error-handling。
- 相关技能:type switches、comma-ok 或接口满足性检查时,见 go-interfaces。
- 相关技能:减少嵌套深度或解决格式问题时,见 go-style-core。
- 相关技能:使用 if-init、`:=` redeclaration 或减少变量作用域时,见 go-declarations。
适用边界 · 注意事项
- 需要错误流模式(结构化 guard clauses、early returns、error-first patterns)时,应改用 go-error-handling。
- 需要 type switches、comma-ok 或接口满足性检查时,应改用 go-interfaces。
- 需要减少嵌套深度、格式问题或声明作用域规则时,应改用 go-style-core 或 go-declarations。