作用域与生命周期不是一个概念,作用域是变量或其它声明出现的区域,是一个在编译阶段关注的问题,而生命周期是一个变量能被其它部分所引用的起止时间,是一个运行时的问题。如果块级作用域内部的一个变量的指针被赋值给包级别的变量(俗称逃逸),那么这个变量的作用域还是在这个块内,但这个变量的值却会始终存在,你无法通过变量本身访问它,但可以通过外部的指针来访问它。
golang是典型的块级作用域,块(block) 有不同的层级,最外层是全局块,里面有 int, len() 等,再然后有 包 / 文件 / 函数 / if / for 等。
在同一个级别的作用域内,变量名必须唯一,但在它的下级作用域可以再次声明一个同名的变量,从而覆盖上层块。
下面看一个隐式块级作用域的例子
if f, err := os.Open(fname); err != nil {
return err
}
f.Close() // 编译失败,因为 f 的作用域位于 if 这个块内,所以无法在块外使用
调整代码,使之通过编译
f, err := os.Open(fname)
if err != nil {
return err
}else{
// 使用逻辑
f.Close()
}
上面的代码通过了编译,并且将使用逻辑放入了单独的块内,可读性强。但是,它将两个变量的作用域提升到了块外,这是没有必要的。
继续改进,尽量将变量放在更小的作用域内
if f, err := os.Open(fname); err != nil {
return err
} else {
// 使用逻辑
f.Close()
}
ferrif