【Go入门教程2】基本构成元素:标识符(identifier)、关键字(keyword 25个)、字面量(literal)、分隔符(delimiter)、和 操作符(operator)
基本构成要素
Go 的语言符号 又称 词法元素,共包括 5 类内容——标识符(identifier)、关键字(keyword)、字面量(literal)、分隔符(delimiter) 和 操作符(operator),它们可以组成各种表达式 和 语句,而后者都无需以分号结尾。
标识符
标识符可以表示 程序实体,前者即为后者的名称。在一般情况下,同一个代码块中不允许出现同名的程序实体。使用不同代码包中的程序实体需要用到限定标识符,比如:os.O_RDONLY。
另外,Go 中还存在着一些特殊的标识符,叫作预定义标识符,它们在 Go 源码中声明的。这类标识符包括以下几种。
- 所有基本数据类型的名称
- 接口类型 error
- 常量 true、false 和 iota。
所有的 内建函数 的名称,即 append、cap、close、complex、copy、delete、imag、len、make、new、panic、print、println、real 和 recover。
这里强调一下 空标识符,它由一个下划线 _ 表示,一般用在变量声明 或 代码包 导入语句中。若在代码中存在一个变量 x,但是却不存在任何对它的使用,则编译器会报错。如果在变量 x 的声明代码后添加这样一行代码:
_ = x
就可以绕过编译器检查,使它不产生任何编译错误。这是因为这段代码确实用到了变量 x,只不过它没有在变量 x 上进行任何操作,也没有将它赋值给任何其他变量。空标识符就像一个垃圾桶。在相关初始化工作完成后,操作对象就会被弃之不用。
关键字
关键字 是被编程语言保留的字符序列,编程人员不能把它们用作标识符。因此,关键字也称为 保留字。
Go 的关键字可以分为 3 类,包括用于 程序声明的关键字、用于程序实体声明 和 定义 的关键字,以及用于程序流程控制的关键字,如下图所示:
类 别 | 关 键 字 |
---|---|
程序声明 | import 和 package |
程序实体 声明 和 定义 | chan,const,func,interface,map,struct,type 和 var |
程序流程控制 | go,select,break,case,continue,default,defer,else,fallthrough,for,goto,if,range,return 和 switch |
Go 关键字共有 25 个,其中与并发编程有关的关键字有 go、chan 和 select。
这里特别说明一下关键字 type 的用途——类型声明。我们可以使用它声明一个 自定义类型:
type myString string
这里把名为 myString 的类型声明为 string 类型的一个别名类型。反过来说,string 类型是 myString 类型的 潜在类型。再看另一个例子,基本类型 rune 是 int32 类型的一个别名类型。int32 类型就是 rune 类型的潜在类型。虽然类型及其潜在类型是不同的 两个 类型,但是它们的值可以进行类型转换,例如:string(myString("ABC"))
。这样的类型转换不会产生新值,几乎没什么代价。
自定义的类型一般都会基于 Go 中一个或多个预定义类型,就像上面的 myString 和 string 那样。如果为自定义类型关联若干方法(函数的变体),那么还可以让它成为某个或某些接口类型的实现类型。另外,还有一个比较特殊的类型,叫 空接口。它的类型字面量是 interface{}
。在 Go 语言中,任何类型都是 空接口 类型的实现类型。
字面量
简单来说,字面量就是 值 的一种 标记法。但是,在 Go 中,字面量的含义要更加广泛一些。我们常常用到的字面量有以下 3 类。
1、用于表示基础数据类型 值 的各种字面量。这是最常用的一类字面量,例如,表示浮点数类型值的 12E-3。
2、用于构造各种自定义的复合数据类型的 类型 字面量。例如,下面的字面量定义了一个名称为 Name 的结构体类型:
type Name struct {
Forename string
Surname string
}
3、用于表示复合数据类型的 值 的复合字面量,它可以用来构造 struct(结构体)、array(数组)、slice(切边) 和 map(字典) 类型的值。复合字面量 一般由字面类型 以及 被花括号包裹的复合元素的列表组成。字面类型 指的就是 复合数据类型 的名称。
例如,下面的复合字面量构造出了一个 Name 类型的值:
Name{Forename: "Robert", Surname: "Hao"}
其中 Name 表示这个值的类型,紧随其后的就是由键值对表示的复合元素列表。
操作符
操作符,也称 运算符。它是用于执行特定算术 或 逻辑操作的符号,操作的对象称为 操作数。Go 有如下操作符:
符 号 | 说 明 | 示 例 |
---|---|---|
|| | 逻辑或操作,二元操作符,逻辑操作符 | true || false // 结果为 true |
&& | 逻辑与操作,二元操作符,逻辑操作符 | true && false // 结果为 false |
== | 相等判断操作,二元操作符,比较操作符 | "abc" == "abc" // 结果为 true |
!= | 不等判断操作,二元操作符,比较操作符 | "abc" != "Abc" // 结果为 true |
< | 小于判断操作,二元操作符,比较操作符 | 1 < 2 // 结果为 true |
<= | 小于或等于判断操作,二元操作符,比较操作符 | 1 <= 2 // 结果为 true |
> | 大于判断操作,二元操作符,比较操作符 | 3 > 2 // 结果为 true |
>= | 大于或等于操作判断,二元操作符,比较操作符 | 3 >= 2 // 结果为 true |
+ | 求和操作,一元操作符,二元操作符,算术操作符。若为一元操作符,不会对原值产生任何影响 | +1 // 结果为 1 1 + 2 // 结果为 3 |
- | 求差操作,一元操作符,二元操作符,算术操作符。若为一元操作符,则表示求反操作。 | -1 // 结果为 -1(1的相反数) 1 - 3 // 结果为 -2 |
| | 按位或操作,二元操作符,算术操作符 | 5 | 11 // 结果为 15 |
^ | 按位异或操作,一元操作符,二元操作符,算术操作符。若为一元操作符,则表示按位补码操作。 | 5 ^ 11 // 结果为 14 ^5 // 结果为 -6 |
* | 求乘操作,一元操作符,二元操作符,算术操作符,地址操作符。若为地址操作符,则表示取值操作 | *p // 若 p 为指向整数类型值 2 的指针类型值,则结果为 2 2 * 5 // 结果为 10 |
/ | 求商操作,二元操作符,算术操作符 | 10 / 5 // 结果为 2 |
% | 求余数操作,二元操作符,算术操作符 | 12 % 5 // 结果为 2 |
<< | 按位左移操作,二元操作符,算术操作符 | 4 << 2 // 结果为 16 |
>> | 按位右移操作,二元操作符,算术操作符 | 4 >> 2 // 结果为 1 |
& | 按位与操作,一元操作符,二元操作符,算术操作符,地址操作符,则表示取址操作 | &v // 结果为标识符 v 所代表的值在内存中的地址 5 & 11 // 结果为 1 |
&^ | 按位清除操作,二元操作符,算术操作符 | 5 &^ 11 // 结果为 4 |
! | 逻辑非操作,一元操作符,逻辑操作符 | !b // 若 b 的值为 false,则表达式的结果为 true |
<- | 接收操作,一元操作符,接收操作符 | <- ch // 若 ch 代表了元素类型为 byte 的通道类型值,则此表达式就表示从 ch 中接收一个 byte 类型值的操作 |
Go 的操作符一共有 21 个,并分为 5 类:算术操作符、比较操作符、逻辑操作符、地址操作符 和 接收操作符。
当一个表达式中存在多个操作符时,就涉及操作顺序的问题。在 Go 中,一元操作符拥有最高的优先级,而二元操作符的优先级如下表所示:
优 先 级 (数字越大,优先级越高) |
操 作 符 |
---|---|
5 | *、/、%、<<、>>、&、&^ |
4 | +、-、|、^ |
3 | ==、!=、<、<=、>、>= |
2 | && |
1 | || |
如果在一个表达式中出现了处于相同优先级的多个操作符,且这些操作符之间存在操作数,那么就会按照从左到右的顺序进行操作。当然,我们可以使用圆括号显示地改变原有的操作顺序,例如表达式 a << (4 * b) & c
等同于 (a << (4 * b)) & c
,即子表达式 4 * b
会先被求值。
最后需要注意的是,++ 和 -- 是语句,而不是表达式,因而他们不存在于任何操作优先级层次之内。例如 表达式 *p--
等同于 (*p)--
。
表达式
表达式 是把 操作符 和 函数 作用于操作数的计算方法。在 Go 中,表达式 是构成具有词法意义的代码的最基本元素。Go 的表达式有很多种,具体如下表所示:
种 类 | 用 途 | 示例 |
---|---|---|
选择表达式 | 选择一个值中的字段或方法 | context.Speaker // context 是变量名 |
索引表达式 | 选取数组、切片、字符串 或 字典值 中的某个元素 | array1[1] // array1 表示一个数组值,其长度必须大于 1 |
切片表达式 | 选取数组、数组指针、切片 或 字符串值中的某个范围的元素 | slice[0:2] // slice1 表示一个切片值,其容量必须大于 或 等于 2 |
类型断言 | 判断一个接口值的实际类型是否为某个类型,或一个非接口值的类型是否实现了某个接口类型 | v1.(I1) // v1 表示一个接口值,I1 表示一个接口类型 |
调用表达式 | 调用一个函数 或 一个值的方法 | v1.M1() // v1 表示一个值,M1 表示与该值关联的一个方法 |
关于 类型断言,有 2 点需要注意一下:
1、如果 v1 是一个非接口值,那么必须在做类型断言之前把它转换成 接口值。
因为 Go 中的任何类型都是 空接口类型 的实现类型,所以一般会这样做:interface{}(v1).(I1)
。
2、如果类型断言的结果为否,就意味着该类型断言是失败的。失败的类型断言会引发一个运行时恐慌(或称运行时异常),解决方法是:
var i1, ok = interface{}(v1).(I1)
这里声明并赋值了 2 个变量,其中 ok 是布尔类型的变量,它的值体现了类型断言的成败。如果成功,i1 就会是经过类型转换后的 I1 类型的值,否则它将会是 I1 类型的零值(或称默认值)。如此一来,当类型断言失败时,运行时恐慌就不会发生。
关键字 var 用于变量的声明。在它 和 等号(=) 之间可以有多个由逗号(,)隔开的变量名。这种在一条语句中同时为多个变量赋值的方式叫 平行赋值。另外,如果在声明变量的同时进行赋值,那么等号左边的变量类型可以省略。如果不使用上述几个技巧的话,上面那条语句可以写成:
var i1 I1
var ok bool
i1, ok = interface{}(v1).(I1)
另一方面,上面那条语句还可以简写成:
i1, ok := interface{}(v1).(I1)
这种简写方式只能出现在函数中。有了符号 :=,关键字 var 也可以省略了,这叫 短变量声明。
摘自:《Go并发编程实战(第2版)》
【Go入门教程2】基本构成元素:标识符(identifier)、关键字(keyword 25个)、字面量(literal)、分隔符(delimiter)、和 操作符(operator)的更多相关文章
- 《JavaScript语言入门教程》记录整理:入门和数据类型
目录 入门篇 js介绍 历史 基本语法 数据类型 概述 null 和 undefined 数值 字符串 对象 函数 数组 本系列基于阮一峰老师的<JavaScrip语言入门教程>或< ...
- PyTorch 60 分钟入门教程
PyTorch 60 分钟入门教程:PyTorch 深度学习官方入门中文教程 http://pytorchchina.com/2018/06/25/what-is-pytorch/ PyTorch 6 ...
- JavaSE(二)标识符,关键字,数据类型
一.标识符和关键字 1.具有特殊作用的分隔符:分号;.花括号{}.圆括号().空格.圆点 . 2.标识符规则:用于给程序中变量.类.方法命名的符号. Ja ...
- D3.js的v5版本入门教程(第五章)—— 选择、插入、删除元素
D3.js的v5版本入门教程(第五章) 1.选择元素 现在我们已经知道,d3.js中选择元素的函数有select()和selectAll(),下面来详细讲解一下 假设我们的<body>中有 ...
- D3.js的v5版本入门教程(第三章)—— 选择元素和绑定数据
D3.js的v5版本入门教程(第三章) 在D3.js中,选择元素和绑定元素是最基本的内容,也是很重要的内容,等你看完整个教程后你会发现,这些D3.js教程都是在选择元素和绑定元素的基础上展开后续工作的 ...
- 【OpenCV入门教程之十四】OpenCV霍夫变换:霍夫线变换,霍夫圆变换合辑
http://blog.csdn.net/poem_qianmo/article/details/26977557 本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog ...
- 毫无基础的人入门Python,Python入门教程
随着人工智能的发展,Python近两年也是大火,越来越多的人加入到Python学习大军,对于毫无基础的人该如何入门Python呢?这里整理了一些个人经验和Python入门教程供大家参考. 如果你是零基 ...
- 21分钟 MySQL 入门教程(转载!!!)
21分钟 MySQL 入门教程 目录 一.MySQL的相关概念介绍 二.Windows下MySQL的配置 配置步骤 MySQL服务的启动.停止与卸载 三.MySQL脚本的基本组成 四.MySQL中的数 ...
- WebGL入门教程(二)-webgl绘制三角形
前面已经介绍过了webgl,WebGL入门教程(一)-初识webgl(http://www.cnblogs.com/bsman/p/6128447.html),也知道了如何绘制一个点,接下来就用web ...
随机推荐
- HDU 1229 还是A+B(A+B陶冶情操)
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1229 解题报告:A+B #include<cstdio> int main() { int ...
- 01 workerman之GatewayWorker框架简单使用
1.GatewayWorker框架是什么? GatewayWorker基于Workerman开发的一个项目框架,用于快速开发TCP长连接应用,例如app推送服务端.即时IM服务端.游戏服务端.物联网. ...
- [转]Restrict关键字
0 定义 C99中新增加的用于修饰指针的关键字,用于表示该指针所指向的内存,只有通过该指针访问得到(如下ptr指向的内存单元只能通过ptr访问得到).从而可以让编译器对代码进行优化,生成更有效率的汇编 ...
- Python学习四|变量、对象、引用的介绍
变量 变量创建:一个变量也就是变量名,就像a,当代码第一次赋值时就创建了它.之后的赋值将会改变已创建的变量名的值,从技术上讲,Python在代码运行之前先检测变量名,可以当成是最初的赋值创建了变量. ...
- 刘昕鑫 C# 特性详解
C# 特性详解 特性(attribute)是被指定给某一声明的一则附加的声明性信息. 在C#中,有一个小的预定义特性集合.在学习如何建立我们自己的定制特性(custom attributes)之前,我 ...
- centos7更改网卡名
虚拟机中安装centos7,分配两张网卡,安装完成后,使用ip addr 命令查看网卡,发现网卡名称为ens33 和 ens34,不符合平时的使用习惯,想把网卡名改为eth0和eth1,具体操作步骤如 ...
- maven dependencies 报错
maven配置的环境变量有问题: 用最新的maven替换系统默认的setting.xml文件即可
- Win7下如何使用GCC编译器
很多Linux的爱好者都很熟悉GCC编译器,但是对面初学者,如何去学习GCC使用GCC ,很多人都是直接在电脑上装一个虚拟机,这样不仅安装麻烦,而且占用了很多电脑资源,今天我来教大家如何在Win7使用 ...
- C#用Oracle.DataAccess中连接Oracle要注意版本问题!
客户端Oracle.DataAccess.dll与服务器版本不一致时,如下修改:1.在客户端Web.config中,增加如下配置:<runtime> <assemblyBinding ...
- Asp.Net Mvc5 结合 SignalR2.0+ 实现消息交互简单例子
Nuget添加 SignalR包 1.构建一个MyHubServer服务端类 定义类的特性标签为 [HubName("chatHub")] public class MyHubSe ...