# Effective Go: 控制结构

这是我参与11月更文挑战的第17天,活动详情查看:2021最后一次更文挑战

Go 的控制结构与 C 的控制结构相关,但在重点方面有所不同。Go没有 do 或 while 循环,只有一个稍微概括的 for;切换更灵活; if 和 switch 接受一个可选的初始化语句,比如 for ; break 和 continue 可选标签来标识要中断或继续的内容;并且有新的控制结构,包括类型开关和多路通信多路复用器,选择。语法也略有不同:没有括号,主体必须始终以大括号分隔。

IF

在 Go 中,一个简单的 if 看起来像这样:

if x > 0 {
    return y
}
复制代码

强制大括号鼓励在多行上编写简单的 if 语句。无论如何这样做都是很好的风格,尤其是当主体包含一个控制语句时,例如 return 或 break。

由于 if 和 switch 接受初始化语句,因此经常会看到用于设置局部变量的语句。

if err := file.Chmod(0664); err != nil {
    log.Print(err)
    return err
}
复制代码

在 Go 库中,你会发现当一个 if 语句没有流入下一个语句时——也就是说,主体以 break、continue、goto 或 return 结尾——不必要的 else 被省略了。

f, err := os.Open(name)
if err != nil {
    return err
}
codeUsing(f)
复制代码

下面的代码展示了,为了防范一系列错误条件的怎么进行处理的示例。如果判断成功则控制逻辑向下运行,则代码可读性良好,从而消除出现的错误情况。由于错误案例往往以 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)
复制代码

重新申报和重新分配

旁白:上一节中的最后一个示例详细说明了 := 短声明形式的工作原理。调用 os.Open 的声明如下:

f, err := os.Open(name)
复制代码

该语句声明了两个变量,f 和 err。几行之后,对 f.Stat 的调用显示,

d, err := f.Stat()
复制代码

看起来好像声明了 d 和 err。但是请注意,err 出现在两个语句中。这种重复是合法的:err 由第一条语句声明,但仅在第二条语句中重新赋值。这意味着对 f.Stat 的调用使用上面声明的现有 err 变量,并且只是给它一个新值。

在 := 声明中,即使已经声明了变量 v 也可能出现,前提是:

  • 此声明的变量与现有声明在同一范围内(如果已声明变量在外部范围,则该声明将创建一个新变量 §),
  • 初始化中的相应值可分配给 v
  • 并且至少有一个被其他地方声明创建的相同变量。

这种不寻常的属性是纯粹的实用主义,可以很容易地使用单个 err 值,例如,在很长的 if-else 链中。你会看到它经常被使用。

§ 这里值得注意的是,在 Go 中,函数参数和返回值的范围与函数体中的变量相同,即使它们在词法上是出现在包围体的大括号之外的。

猜你喜欢

转载自juejin.im/post/7031911422980423687