mcpField
G
go-control-flow

go-control-flow

github.com/cxuu开发1861.2k 次安装19 周前更新
代码仓库

关于 go-control-flow

面向 Go 开发的编码技能,涵盖控制流惯用法、变量作用域、循环、switch 和空白标识符,帮助开发者应用常见模式并避免作用域与流程错误。

主要功能

  1. 01条件初始化与作用域
  2. 02卫语句与提前返回
  3. 03短变量声明与遮蔽
  4. 04for 和 range 循环规则
  5. 05switch 跳出与空白标识符

适用场景

  1. 01将变量限制在 if 或 switch 内
  2. 02检查短变量声明中的遮蔽问题
  3. 03正确处理 map 和字符串遍历

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/cxuu/golang-skills --skill go-control-flow

安装后在 Claude Code 中输入/go-control-flow确认已加载。

附带文件references/BLANK-IDENTIFIER.mdreferences/SWITCH-PATTERNS.md

详细介绍

Go 控制流

资源路由

  • references/SWITCH-PATTERNS.md - 使用 switch 语句、类型 switch、fallthrough 或带标签的 break 时阅读。
  • 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
}
// lots of code that uses x

缩进错误流程(守卫子句)

当 if 语句体以 break、continue、goto 或 return 结束时,省略不必要的 else。让成功路径保持不缩进:

f, err := os.Open(name)
if err != nil {
    return err
}
d, err := f.Stat()
if err != nil {
    f.Close()
    return err
}
codeUsing(f, d)

如果 if 已经返回,就不要把正常流程藏在 else 中。


重新声明与重新赋值

:= 短变量声明允许在同一作用域内重新声明变量:

f, err := os.Open(name)  // declares f and err
d, err := f.Stat()       // declares d, reassigns err

即使变量 v 已经声明过,v 仍可出现在 := 声明中,但须满足:

  1. 该声明与现有 v 位于同一作用域
  2. 该值可赋给 v
  3. 该声明还会创建至少一个其他新变量
变量遮蔽

警告:如果 v 在外层作用域中声明,:= 会创建一个新变量来遮蔽它——这是常见的错误来源:

// Bug: ctx inside the if block shadows the outer ctx
if *shortenDeadlines {
    ctx, cancel := context.WithTimeout(ctx, 3*time.Second)
    defer cancel()
}
// ctx here is still the original — the shadowed ctx didn't escape

// Fix: use = instead of :=
var cancel func()
ctx, cancel = context.WithTimeout(ctx, 3*time.Second)

For 循环

Go 的唯一循环结构是 for,它统一了 while、do-while 和 C 风格的 for:

// Condition-only (Go's "while")
for x > 0 {
    x = process(x)
}

// Infinite loop
for {
    if done() { break }
}

// C-style three-component
for i := 0; i < n; i++ { ... }
Range

range 可遍历切片、映射、字符串和通道:

for i, v := range slice { ... }   // index + value
for k, v := range myMap { ... }   // key + value (non-deterministic order)
for i, r := range "héllo" { ... } // byte index + rune (not byte)
for v := range ch { ... }         // receives until channel closed

主要规则:

  • 遍历字符串时会得到符文,而非字节——i 是字节偏移量
  • 遍历映射的顺序是非确定的——不要依赖其顺序
  • 使用 _ 丢弃索引或值: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:带标签的 Break

在 for 循环内的 switch 中,break 只会跳出 switch。 使用带标签的 break 可退出外层循环:

Loop:
    for _, v := range items {
        switch v.Type {
        case "done":
            break Loop  // breaks the for loop
        }
    }

有关类型 switch,请参阅 go-interfaces:Type Switch。


空白标识符

切勿随意丢弃错误——之后可能会发生 nil 解引用 panic。

将编译期接口断言转至 go-interfaces。


快速参考

模式Go 惯用写法
If 初始化if err := f(); err != nil { }
提前返回if 语句体返回时省略 else
重新声明同一作用域内 := 会重新赋值 + 声明新变量
遮蔽陷阱内层作用域中的 := 会创建新变量
并行赋值i, j = i+1, j-1
无表达式的 switchswitch { case cond: }
逗号分隔的 casecase 'a', 'b', 'c':
不自动贯穿默认行为(需要时显式使用 fallthrough)
从 switch 中退出循环break Label
丢弃值_, err := f()
副作用导入import _ "pkg"
接口检查转至 go-interfaces

相关技能

  • 错误流程:在组织守卫子句、提前返回或错误优先模式时,请参阅 go-error-handling
  • 类型 switch:使用类型 switch、comma-ok 惯用法或接口满足性检查时,请参阅 go-interfaces
  • 减少嵌套:减少嵌套深度或解决格式问题时,请参阅 go-style-core
  • 变量作用域:使用 if-init、:= 重新声明或缩小变量作用域时,请参阅 go-declarations

评论

支持 Markdown