在 Go 语言中,代码块内声明的标识符,只能在代码块内使用。例如函数体是个代码块,里面定义的变量,只要没发生逃逸,在外部无法访问。 但有一种特殊情况,就是在支持初始化子语句的流程语句中,初始化子语句中定义的变量,作用域会延伸到条件对应的代码块之外。请看代码:
package main
import "fmt"
func main() {
if a := 1; false {
fmt.Println(a)
//fmt.Println(b) // 不能引用下面语句定义的块级变量
} else if b := 2; a > b {
fmt.Println(a - b) // 可以引用上面语句定义的块级变量
} else {
fmt.Println(a + b) // 在最后 a 和 b 都可以引用
}
}
左看右看也想不明白,为什么 else if
中定义的变量 b
也能在 else
块中使用?如果有更多条件判断,那么前一个 else if
中定义的变量,在之后所有 else if
块中都能使用。
在 C++ 中,if
中定义的变量 a
,可以跨整个流程语句,else if
中定义的变量明确不能在其他 else
代码块中引用:
#include <iostream>
int main() {
if (int a = 1; false) { // a 在整个 if-else 结构中可见
std::cout << a << std::endl;
} else if (int b = 2; a > b) { // a 可访问
std::cout << a - b << std::endl;
} else {
std::cout << a << std::endl; // a 可访问
// std::cout << b << std::endl; // 错误:b 不可访问
}
return 0;
}
在 C# 中,规定更是严格,if
和 else if
中定义的变量,只能在随后的代码块中使用,不能跨到代码块:
public class Program {
public static void Main() {
if (int a = 1; false) {
Console.WriteLine(a);
} else if (int b = 2; a > b) { // 错误:a 不可访问
Console.WriteLine(a - b);
} else {
Console.WriteLine(a + b); // 错误:a 和 b 都不可访问
}
}
}
有本 Go 语言书管这叫「惰性求值」行为,但我也仅仅是知道有这么个现象,不明白为什么会设计成这样?
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.