[TOC]

if

标识符的重声明和标识符的遮蔽

上述代码被执行完毕之后,第二次声明的number变量的值会是7,而第一次声明的number变量的值仍会是``。

switch

for语句

最后,我们来说一下break语句和continue语句。它们都可以被放置在for语句的代码块中。break被执行时会使其所属的for语句的执行立即结束,continue被执行时会使当次迭代被中止(当次迭代的后续语句会被忽略)而直接进入到下一次迭代。

select语句

select语句属于条件分支流程控制方法,不过它只能用于通道。它可以包含若干条case语句,并根据条件选择其中的一个执行。进一步说,select语句中的case关键字只能后跟用于通道的发送操作的表达式以及接收操作的表达式或语句。

如果该select语句被执行时通道ch1ch2中都没有任何数据,那么肯定只有default case会被执行。但是,只要有一个通道在当时有数据就不会轮到default case执行了。显然,对于包含通道接收操作的case来讲,其执行条件就是通道中存在数据(或者说通道未空)。如果在当时有数据的通道多于一个,那么Go语言会通过一种伪随机的算法来决定哪一个case将被执行。

我们一直在说case执行条件的满足与否取决于其操作的通道在当时的状态。这里特别强调一点,即:未被初始化的通道会使操作它的case永远满足不了执行条件。对于针对它的发送操作和接收操作来说都是如此。

defer语句 [dɪˈfɚ] 推迟

defer语句仅能被放置在函数或方法中。它由关键字defer和一个调用表达式组成。注意,这里的调用表达式所表示的既不能是对Go语言内建函数的调用也不能是对Go语言标准库代码包unsafe中的那些函数的调用。

注意,当这条defer语句被执行的时候,其中的这条表达式语句并不会被立即执行。它的确切的执行时机是在其所属的函数(这里是readFile)的执行即将结束的那个时刻。也就是说,在readFile函数真正结束执行的前一刻,file.Close()才会被执行。

注意,当一个函数中存在多个defer语句时,它们携带的表达式语句的执行顺序一定是它们的出现顺序的倒序。

最后,对于defer语句,我还有两个特别提示:

  1. defer携带的表达式语句代表的是对某个函数或方法的调用。这个调用可能会有参数传入,比如:fmt.Print(i + 1)。如果代表传入参数的是一个表达式,那么在defer语句被执行的时候该表达式就会被求值了。注意,这与被携带的表达式语句的执行时机是不同的。
  2. 如果defer携带的表达式语句代表的是对匿名函数的调用,那么我们就一定要非常警惕。正确的用法是:把要使用的外部变量作为参数传入到匿名函数中。