Go程序设计语言2.7 作用域

2.7 作用域


声明将名字和程序实体关联起来,如一个函数或一个变量。声明的作用域是指用到声明时所声明名字的源代码段。

不要将作用域和生命周期混淆。声明的作用域是声明在程序文本中出现的区域,它是一个编译时属性。变量的生命周期是变量在程序执行期间能被程序的其他部分所引用的起止时间,它是一个运行时属性。

语法块(block)是由大括号围起来的一个语句序列,比如一个循环体或函数体。在语法块内部声明的变量对块外部不可见。块把声明包围起来,并且决定了它的可见性。我们可以把块的概念推广到其他没有显式包含在大括号中的声明代码,将其统称为词法块。包含了全部源代码的词法块,叫作全局块。每一个包,每一个文件,每一个for、if和switch语句,以及switch和select语句中的每一个条件,都是写在一个词法块里的。当然,显式写在大括号语法里的代码块也算是一个词法块。

一个声明的词法块决定声明的作用域大小。像int、len和true等内置类型、函数或常量在全局块中声明并且对于整个程序可见。在包级别(就是在任何函数外)的声明,可以被同一个包里的任何文件引用。导入的包(比如在tempconv例子中的fmt)是文件级别的,所以它们可以在同一个文件内引用,但是不能在没有另一个import语句的前提下被同一个包中其他文件中的东西引用。许多声明(像tempconv.CToF函数中变量c的声明)是局部的,仅可在同一个函数中或者仅仅是函数的一部分所引用。

控制流标签(如break、continue和goto语句使用的标签)的作用域是整个外层的函数(enclosing function)。

一个程序可以包含多个同名的声明,前提是它们在不同词法块中。例如可以声明一个和包级别变量同名的局部变量。或者像2.3.3节展示的,可以声明一个叫作new的参数,即使它是一个全局块中预声明的函数。然而,不要滥用,重声明所涉及的作用域越广,越可能影响其他的代码。

当编译器遇到一个名字的引用时,将从最内层的封闭词法块到全局块寻找其声明。如果没有找到,它会报“undeclared name”错误;如果在内层和外层块都存在这个声明,内层的将先被找到。这种情况下,内层声明将覆盖外部声明,使它不可访问:

 

 

在函数里面,词法块可能嵌套很深,所以一个局部变量声明可能覆盖另一个。很多词法块使用if语句和for循环这类控制流结构构建。下面的程序有三个称为x的不同的变量声明,因为每个声明出现在不同的词法块。(这个例子只是用来说明作用域的规则,风格并不完美!)

 

表达式x[i]和x + 'A' - 'a'都引用了在外层声明的x,稍后我们会解释它。(注意,后面的表达式不同于unicode.ToUpper函数。)

如上所述,不是所有的词法块都对应于显式大括号包围的语句序列,有一些词法块是隐式的。for循环创建了两个词法块:一个是循环体本身的显式块,以及一个隐式块,它包含了一个闭合结构,其中就有初始化语句中声明的变量,如变量i。隐式块中声明的变量的作用域包括条件、后置语句(i++),以及for语句体本身。

下面的例子也有三个名字为x的变量,每一个都在不同的词法块中声明:一个在函数体中,一个在for语句块中,一个在循环体中。但只有两个块是显式的:

 

像for循环一样,除了本身的主体块之外,if和switch语句还会创建隐式的词法块。下面的if-else链展示x和y的作用域:

 

第二个if语句嵌套在第一个中,所以第一个语句的初始化部分声明的变量在第二个语句中是可见的。同样的规则可以应用于switch语句:条件对应一个块,每个case语句体对应一个块。

在包级别,声明的顺序和它们的作用域没有关系,所以一个声明可以引用它自己或者跟在它后面的其他声明,使我们可以声明递归或相互递归的类型和函数。如果常量或变量声明引用它自己,则编译器会报错。

在以下程序中:

 

f变量的作用域是if语句,所以f不能被接下来的语句访问,编译器会报错。根据编译器的不同,也可能收到其他报错:局部变量f没有使用。

所以通常需要在条件判断之前声明f,使其在if语句后面可以访问:

 

你可能希望避免在外部块中声明f和err,方法是将Stat和Close的调用放到else块中:

 

通常Go中的做法是在if块中处理错误然后返回,这样成功执行的路径不会被变得支离破碎。

短变量声明依赖一个明确的作用域。考虑下面的程序,它获取当前的工作目录然后把它保存在一个包级别的变量里。这通过在main函数中调用os.Getwd来完成,但是最好可以从主逻辑中分离,特别是在获取目录失败是致命错误的情况下。函数log.Fatalf输出一条消息,然后调用os.Exit(1)退出。

 

因为cwd和err在init函数块的内部都尚未声明,所以:=语句将它们都声明为局部变量。内层cwd的声明让外部的声明不可见,所以这个语句没有按预期更新包级别的cwd变量。

当前Go编译器检测到局部的cwd变量没有被使用,然后报错,但是不必严格执行这种检查。进一步做一个小的修改,比如增加引用局部cwd变量的日志语句就可以让检查失效。

 

 

全局的cwd变量依然未初始化,看起来一个普通的日志输出让bug变得不明显。

处理这种潜在的问题有许多方法。最直接的方法是在另一个var声明中声明err,避免使用:=。

 

现在我们已经看到包、文件、声明以及语句是如何来构成程序的。接下来的两章将要讨论数据的结构。

 

 

时间: 2024-09-20 00:11:08

Go程序设计语言2.7 作用域的相关文章

Go程序设计语言导读

前 言 The Go Programming Language "Go是一种开源的程序设计语言,它意在使得人们能够方便地构建简单.可靠.高效的软件."(来自Go官网golang.org) Go在2007年9月形成构想,并于2009年11月发布,其发明人是Robert Griesemer.Rob Pike和Ken Thompson,这几位都任职于Google.该语言及其配套工具集使得编译和执行既富有表达力又高效,而且使得程序员能够轻松写出可靠.健壮的程序. Go和C从表面上看起来相似,而

【软考教程】程序设计语言基础

继续软考教程的学习,在第1章,我们主要是对计算机的组成和工作原理做了一定了解,可以说,在他的带领下,我们对计算机硬件方面的知识,有了更加坚实的基础. 第2章,程序设计语言基础知识.不看内容,光从标题来看,并不会觉得陌生."程序设计语言",至今,我们已经接触过不止一种了,从最初的VB.到后来的VB.NET.C#.C++,软考前个阶段,我们还见到了早有耳闻的Java世界. 那么,下面就跟随着"设计语言"的脚步,一起发现编程路上美丽的风光吧. 想要对程序设计语言有个宏观上

最受欢迎的十大程序设计语言排行榜更新(10月版)

在最受欢迎的程序设计语言排行榜上最值得关注的是Ruby从一年前的第十三名上升到第十位.无论如何,按照TIOBE程序设计区域指标的数据,这是个神奇的事情.TIOBE程序设计区域指标用于标识程序设计语言的普及度,并根据世界范围的熟练工程师.课程和第三方供应商对程序设计语言的实际使用率,每月更新一次数据. 流行的搜索引擎Google. MSN和Yahoo!都被用于计算此指标的评估结果,根据TIOBE所言.TIOBE在它的网站上发出如下告诫: 注意:TIOBE指标不是为了衡量哪个程设计语言是最好的或者是

c语言编程-这段C程序设计语言书上的代码,运行后按回车只换行并没有输出最长的行,为什么

问题描述 这段C程序设计语言书上的代码,运行后按回车只换行并没有输出最长的行,为什么 #include#define MAXLINE 1000int getline(char line[]int maxline);void copy(char to[]char from[]);main(){int len;int max;char line[MAXLINE];char longest[MAXLINE];max = 0;while ((len = getline(lineMAXLINE))>0)i

《程序分析方法》——1.2 程序设计语言的发展趋势

1.2 程序设计语言的发展趋势 Turbo Pascal编译器的主要编写者以及.NET框架.Delphi和C#之父--Anders Hejlsberg认为,相对于近几十年来计算机硬件的飞速发展,程序语言的改进不是很明显,主要的原因在于人们更关注"工具"."框架"或"开发方法"的变革和创新,而忽略了语言的改进.程序设计离不开程序设计语言,程序设计语言与"工具"."框架"或"开发方法"等一样

Python v3.2发布 面向对象直译式计算机程序设计语言

Python是一种面向对象.直译式计算机程序设计语言,也是一种http://www.aliyun.com/zixun/aggregation/17547.html">功能强大而完善的通用型语言,已经具有十多年的发展历史,成熟且稳定.这种语言具有非常简捷而清晰的语法特点,适合完成各种高层任务,几乎可以在所有的操作系统中运行.目前,基于这种语言的相关技术正在飞速的发展,用户数量急剧扩大,相关的资源非常多. 虽然Python可能被粗略地分类为"脚本语言"(script lan

为什么会有这么多种程序设计语言?

传说人类建造通天塔触怒上帝,上帝施法使人类语言混乱彼此之间无法交流.这就是说各种各样的语言其实就是祸乱之源--只会导致交流的不便.可是看看如今的程 序设计语言的数量,你会怀疑人类是否又在造"通天塔"了?真的有这么多语言的必要吗?我到底要学习多少种程序设计语言才够用呢? 根据维基的资料,可以称得上相对"主流"(有人用.有文档)的程序设计语言至少有600种, 还有大量的商业化失败.实用性不高.语言小众(这里的"语言"指的是编码的语言,一般的程序设计语

《Python语言程序设计》——1.3 程序设计语言

1.3 程序设计语言 关键点:计算机程序,又称为软件,是告诉计算机要做什么的指令集. 计算机并不理解人类的语言,所以程序必须用计算机使用的语言来书写.现在有几百种程序设计语言,开发它们对人们来说可以让程序设计过程更加简单.但是,所有的程序必须被转换成计算机能够理解的语言.1.3.1 机器语言 计算机自己的语言(会因计算机的种类不同而有所不同)是它的机器语言--一套内嵌在计算机内的原始指令集.这些指令以二进制代码的形式存在,所以如果给计算机一条用它自己的语言编写的程序,必须输入二进制码的指令.例如

《程序分析方法》——1.1 程序设计语言发展的四个阶段

1.1 程序设计语言发展的四个阶段 到目前为止,程序设计语言的发展经过了机器语言.汇编语言.高级语言.第四代语言四个阶段,每一个阶段都使程序设计的效率大大提高.我们常常把机器语言称为第 一代程序设计语言,把汇编语言称为第二代程序设计语言,把高级语言称为第三代程序设计语言,把最新的程序设计语言称为第四代语言.1.1.1 机器语言 机器语言是计算机能直接识别和执行的一组机器指令的集合.它是计算机的设计者通过计算机的硬件结构赋予计算机的操作功能.一条机器指令就是机器语言的一个语句,它是一组有意义的二进

《C语言程序设计》一 1.1 程序和程序设计语言

1.1 程序和程序设计语言 1.1.1 程序与程序设计 程序并不是计算机程序设计中独有的概念,在日常生活中我们也常见到这个词,例如一个会议的日程.一场演出的节目单等,这些程序都是由人的一项项的活动组成的,身处其中时通常需要按部就班地一步步完成一系列动作,有序地完成每一项活动也就实现了程序的目标.可以说,对这种活动过程细节动作的描述就是一个"程序". 日常生活中的程序性活动与计算机里的程序执行类似,这一点有助于我们理解计算机的工作方式.日常生活中的程序性活动里有更多变数,许多事情并不是完