Go程序设计语言3.6 常量-阿里云开发者社区

开发者社区> 华章计算机> 正文

Go程序设计语言3.6 常量

简介:
+关注继续查看

3.6 常量


常量是一种表达式,其可以保证在编译阶段就计算出表达式的值,并不需要等到运行时,从而使编译器得以知晓其值。所有常量本质上都属于基本类型:布尔型、字符串或数字。

常量的声明定义了具名的值,它看起来在语法上与变量类似,但该值恒定,这防止了程序运行过程中的意外(或恶意)修改。例如,要表示数学常量,像圆周率,在Go程序中用常量比变量更适合,因其值恒定不变:

 

与变量类似,同一个声明可以定义一系列常量,这适用于一组相关的值:

 

许多针对常量的计算完全可以在编译时就完成,以减免运行时的工作量并让其他编译器优化得以实现。某些错误通常要在运行时才能检测到,但如果操作数是常量,编译时就会报错,例如整数除以0,字符串下标越界,以及任何产生无限大值的浮点数运算。

对于常量操作数,所有数学运算、逻辑运算和比较运算的结果依然是常量,常量的类型转换结果和某些内置函数的返回值,例如len、cap、real、imag、complex和unsafe.Sizeof,同样是常量。

因为编译器知晓其值,常量表达式可以出现在涉及类型的声明中,具体而言就是数组类型的长度:

 

常量声明可以同时指定类型和值,如果没有显式指定类型,则类型根据右边的表达式推断。下例中,time.Duration是一种具名类型,其基本类型是int64,time.Minute也是基于int64的常量。下面声明的两个常量都属于time.Duration类型,通过%T展示:

 

若同时声明一组常量,除了第一项之外,其他项在等号右侧的表达式都可以省略,这意味着会复用前面一项的表达式及其类型。例如:

 

如果复用右侧表达式导致计算结果总是相同,这就并不太实用。假若该结果可变该怎么办呢?我们来看看iota。

3.6.1 常量生成器iota

常量的声明可以使用常量生成器iota,它创建一系列相关值,而不是逐个值显式写出。常量声明中,iota从0开始取值,逐项加1。

下例取自time包,它定义了Weekday的具名类型,并声明每周的7天为该类型的常量,从Sunday开始,其值为0。这种类型通常称为枚举型(enumeration,或缩写成enum)。

 

上面的声明中,Sunday的值为0,Monday的值为1,以此类推。

更复杂的表达式也可使用iota,借用net包的代码举例如下,无符号整数最低5位数中的每一个都逐一命名,并解释为布尔值。

 

随着iota递增,每个常量都按1<<iota赋值,这等价于2的连续次幂,它们分别与单个位对应。若某些函数要针对相应的位执行判定、设置或清除操作,就会用到这些常量。

 

 

下例更复杂,声明的常量表示1024的幂。

 

然而,iota机制存在局限。比如,因为不存在指数运算符,所以无从生成更为人熟知的1000的幂(KB、MB等)。

练习3.13:用尽可能简洁的方法声明从KB、MB直到YB的常量。

3.6.2 无类型常量

Go的常量自有特别之处。虽然常量可以是任何基本数据类型,如int或float64,也包括具名的基本类型(如time.Duration),但是许多常量并不从属某一具体类型。编译器将这些从属类型待定的常量表示成某些值,这些值比基本类型的数字精度更高,且算术精度高于原生的机器精度。可以认为它们的精度至少达到256位。从属类型待定的常量共有6种,分别是无类型布尔、无类型整数、无类型文字符号、无类型浮点数、无类型复数、无类型字符串。

借助推迟确定从属类型,无类型常量不仅能暂时维持更高的精度,与类型已确定的常量相比,它们还能写进更多表达式而无需转换类型。比如,上例中ZiB和YiB的值过大,用哪种整型都无法存储,但它们都是合法常量并且可以用在下面的表达式中:

 

再例如,浮点型常量math.Pi可用于任何需要浮点值或复数的地方:

 

若常量math.Pi一开始就确定从属于某具体类型,如float64,就会导致结果的精度下降。另外,假使最终需要float32值或complex128值,则可能需要转换类型:

 

字面量的类型由语法决定。0、0.0、0i和'\u0000'全都表示相同的常量值,但类型相异,分别是:无类型整数、无类型浮点数、无类型复数和无类型文字符号。类似地,true和false是无类型布尔值,而字符串字面量则是无类型字符串。

根据除法运算中操作数的类型,除法运算的结果可能是整型或浮点型。所以,常量除法表达式中,操作数选择不同的字面写法会影响结果:

 

只有常量才可以是无类型的。若将无类型常量声明为变量(如下面的第一条语句所示),或在类型明确的变量赋值的右方出现无类型常量(如下面的其他三条语句所示),则常量会被隐式转换成该变量的类型。

 

上述语句与下面的语句等价:

 

不论隐式或显式,常量从一种类型转换成另一种,都要求目标类型能够表示原值。实数和复数允许舍入取整:

 

变量声明(包括短变量声明)中,假如没有显式指定类型,无类型常量会隐式转换成该变量的默认类型,如下例所示:

 

注意各类型的不对称性:无类型整数可以转换成int,其大小不确定,但无类型浮点数和无类型复数被转换成大小明确的float64和complex128。Go语言中,只有大小不明确的int类型,却不存在大小不确定的float类型和complex类型,原因是,如果浮点型数据的大小不明,就很难写出正确的数值算法。

要将变量转换成不同的类型,我们必须将无类型常量显式转换为期望的类型,或在声明变量时指明想要的类型,如下例所示:

 

在将无类型常量转换为接口值时(见第7章),这些默认类型就分外重要,因为它们决定了接口值的动态类型。

 

至此,我们已经概述了Go的基本数据类型。下一步就是要说明如何将它们构建成为更大的聚合体,如数组和结构体,更进一步组成数据结构以解决实际的编程问题。第4章以此为主题。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
使用NAT网关轻松为单台云服务器设置多个公网IP
在应用中,有时会遇到用户询问如何使单台云服务器具备多个公网IP的问题。 具体如何操作呢,有了NAT网关这个也不是难题。
22645 0
怎么设置阿里云服务器安全组?阿里云安全组规则详细解说
阿里云服务器安全组设置规则分享,阿里云服务器安全组如何放行端口设置教程
7430 0
阿里云服务器端口号设置
阿里云服务器初级使用者可能面临的问题之一. 使用tomcat或者其他服务器软件设置端口号后,比如 一些不是默认的, mysql的 3306, mssql的1433,有时候打不开网页, 原因是没有在ecs安全组去设置这个端口号. 解决: 点击ecs下网络和安全下的安全组 在弹出的安全组中,如果没有就新建安全组,然后点击配置规则 最后如上图点击添加...或快速创建.   have fun!  将编程看作是一门艺术,而不单单是个技术。
4617 0
使用OpenApi弹性释放和设置云服务器ECS释放
云服务器ECS的一个重要特性就是按需创建资源。您可以在业务高峰期按需弹性的自定义规则进行资源创建,在完成业务计算的时候释放资源。本篇将提供几个Tips帮助您更加容易和自动化的完成云服务器的释放和弹性设置。
8268 0
阿里云服务器安全组设置内网互通的方法
虽然0.0.0.0/0使用非常方便,但是发现很多同学使用它来做内网互通,这是有安全风险的,实例有可能会在经典网络被内网IP访问到。下面介绍一下四种安全的内网互联设置方法。 购买前请先:领取阿里云幸运券,有很多优惠,可到下文中领取。
9513 0
如何设置阿里云服务器安全组?阿里云安全组规则详细解说
阿里云安全组设置详细图文教程(收藏起来) 阿里云服务器安全组设置规则分享,阿里云服务器安全组如何放行端口设置教程。阿里云会要求客户设置安全组,如果不设置,阿里云会指定默认的安全组。那么,这个安全组是什么呢?顾名思义,就是为了服务器安全设置的。安全组其实就是一个虚拟的防火墙,可以让用户从端口、IP的维度来筛选对应服务器的访问者,从而形成一个云上的安全域。
4267 0
阿里云服务器ECS登录用户名是什么?系统不同默认账号也不同
阿里云服务器Windows系统默认用户名administrator,Linux镜像服务器用户名root
1161 0
阿里云ECS云服务器初始化设置教程方法
阿里云ECS云服务器初始化是指将云服务器系统恢复到最初状态的过程,阿里云的服务器初始化是通过更换系统盘来实现的,是免费的,阿里云百科网分享服务器初始化教程: 服务器初始化教程方法 本文的服务器初始化是指将ECS云服务器系统恢复到最初状态,服务器中的数据也会被清空,所以初始化之前一定要先备份好。
3664 0
10059
文章
0
问答
来源圈子
更多
+ 订阅
文章排行榜
最热
最新
相关电子书
更多
文娱运维技术
立即下载
《SaaS模式云原生数据仓库应用场景实践》
立即下载
《看见新力量:二》电子书
立即下载