There are several types of lexical elements in Go language

青灯夜游
Release: 2023-01-12 10:03:16
Original
1777 people have browsed it

There are five types of lexical elements in the Go language: 1. Identifiers, which are character sequences composed of a number of letters (encoded by Unicode), underscores and numbers; 2. Keywords, which are reserved by the programming language. Character sequences that are not allowed to be used by programmers as identifiers can also be called reserved words; 3. Operators are symbols used to perform specific arithmetic operations or logical operations; 4. Delimiters; 5. Literals, which are values A notation.

There are several types of lexical elements in Go language

The operating environment of this tutorial: Windows 7 system, GO version 1.18, Dell G3 computer.

The language symbols of Go language are also called lexical elements, which include five categories: identifier, keyword, operator, delimiter, and Literal , they are the most basic units that make up Go language codes and programs.

In general, spaces, horizontal tabs, carriage returns, and line feeds are ignored unless they are used as part of the delimiter between multiple language symbols. There is no need to insert semicolons explicitly in the Go language. When necessary, the Go language will automatically insert semicolons into the code to separate statements.

The Go language code consists of several Unicode characters. All source codes of the Go language must be encoded in the UTF-8 encoding format of the Unicode encoding specification (that is to say, the written Go language source code file must be UTF- 8 encoding format).

The language symbols of Go language are also called lexical elements, including 5 categories: identifier (identifier), keyword (keyword), operation Character (operator), separator (delimiter), and literal (literal). In general, spaces, horizontal tabs, carriage returns, and line feeds are ignored unless they are used as part of a separator between multiple language symbols. There is no need to insert semicolons explicitly in the Go language. When necessary, the Go language will automatically insert semicolons into the code to separate statements.

The Go language code consists of several Unicode characters. All source codes of the Go language must be encoded in the UTF-8 encoding format of the Unicode encoding specification (that is to say, the written Go language source code file must be UTF- 8 encoding format).

1. Identifier

The identifier of Go language is a character sequence composed of several letters (encoded by Unicode), underscores and numbers; this character sequence The first character of must be a letter.

Note:

  • In Go language code, every identifier must be declared before use.

  • A declaration binds a non-empty identifier to a constant, type, variable, function, or code package.

  • In the same code block, repeated declaration of the same identifier is not allowed (except for assignment statements).

  • Identifiers in a source code file and a code package need to follow this rule.

  • The scope of a declared identifier is the same as the scope of the code block to which it directly belongs.

Strictly speaking, the code package declaration statement is not a statement. Because the code package name does not appear in any scope. The purpose of the code package declaration statement is to identify whether several source code files belong to the same code package, or to specify the default code package reference name when importing the code package.

Qualified identifiers are used to access variables or types in other code packages. For example, when I need to access a constant named O_RDONLY in the code package os, I need to write os.O_RDONLY like this.

Qualified identifiers can be used, and two prerequisites need to be met:

  • The code package to be accessed must be imported in advance;

  • Identifiers in this code package must be exportable.

An exportable identifier also needs to meet two prerequisites:

  • The first character in the identifier name must be uppercase (Go language determines the access permission of this identifier based on the case of the first character in the identifier name. When the first character of the identifier name is uppercase, its access permission is "public", that is The identifier can be accessed by any code in any code package through the qualified identifier; when the first character of the identifier is lowercase, its access permission is "package-level private", that is, only the same identifier as the identifier is accessed. It can only be accessed by code in a code package);

  • The identifier must be the name of a variable or type declared in a code package, or belong to a structure The type's field name or method name.

Predefined identifiers of Go language:

  • The names of all basic data types.
  • Interface type error
  • Constant true, false and iota
  • The names of all built-in functions, namely append, cap, close, complex, copy, delete, imag, len , make, new, panic, print, println, real and recover.

There is an empty identifier in the Go language, which is represented by an underscore and is generally used in a statement that does not require the introduction of a new binding. For example, when we only want to execute the initialization function in a certain code package without using any program entities in this code package, we can write the following import statement:

import _ "runtime/cgo"1.
Copy after login

Among them, "runtime/cgo" represents the identifier of a standard library code package.

2. Keywords

Keywords (also called reserved words) are reserved by programming languages ​​and are not used by programmers as identifiers The character sequence to use.

##Program entity declaration and definitionchan, const, func, interface, map, struct, type, varProgram control flowgo, select, break, case, continue, default, defer, else, fallthrough, for, goto, if, range, return, switch

在Go语言中,程序实体的声明和定义是建立在其数据类型的体系之上的。例如关键字chan、func、interface、map和struct,分别于Go语言的复合数据类型Channel(通道)、Function(函数)、Interface(接口)、Map(字典)和Struct(结构体)相对应。

程序控制流程的关键字,一共15个。其中go和select,这两个主要用于Go语言并发编程。

3、字面量

简单来说,字面量就是值的一种标记法。但是,在Go中,字面量的含义要更加广泛一些。

Go语言代码中用到的字面量有以下3类:

1、表示基础数据类型值的各种字面量。例如,表示浮点数类型值的12E-3。

2、构造各种自定义的复合数据类型的类型字面量。例如,下面表示一个名称为Person的自定义结构体类型:

type Person struct {
	Name 	string
	Age	uint8
	Address	string
}
Copy after login

3、表示复合数据类型的值的复合字面量

被用来构造类型Struct(结构体)、Array(数组)、Slice(切片)和Map(字典)的值。例如,下面的字面量用于表示上面名称为Person的结构体类型的值:

Person {
	Name:"Huazie",
	Age: "21",
	Address: "Nanjing, China"
}
Copy after login

注意:
对复合字面量的每次求值都会导致一个新的值被创建。因此,如上该复合字面量每被求值一次就会创建一个新的Person类型的值。

Go语言不允许在一个此类的复合字面变量中,出现重复的键。如下都是错误,无法通过编译,因为键都有重复。

//表示结构体类型值,有重复的键 Name
Person {Name: "Huazie",Age: "21", Name: "Unknown"}
//表示字典类型值,有重复的键 Age
map[string]string{ Name: "Huazie",Age: "21", Age: "21"}
//表示切片类型值,有重复的键 0
[]string{0: "0", 1: "1", 0: "-1"}
Copy after login

4、类型

一个类型确定了一类值的集合,以及可以在这些值上施加的操作。类型可以由类型名称或者类型字面量指定,分为基本类型和复合类型,基本类型的名称可以代表其自身。

var bookName string1.
Copy after login

如上声明了一个类型为string(基本类型中的一个)、名称为bookName的变量。

其他基本类型(预定义类型)有bool、byte、rune、int/uint、int8/uint8、int16/uint16、int32/uint32、int64/uint64、float32、float64、complex64和complex128。除了bool和string之外的其他基本类型也叫做数值类型。

复合类型一般由若干(也包括零)个其他已被定义的类型组合而成。复合类型有Channel(通道)、Function(函数)、Interface(接口)、Map(字典)、Struct(结构体)、Slice(切片)、Array(数组)和Pointer(指针)。

Go语言中的类型又可以分为静态类型和动态类型。一个变量的静态类型是指在变量声明中给出的那个类型。绝大多数类型的变量都只有静态类型。唯独接口类型的变量例外,它除了拥有静态类型之外,还拥有动态类型(接口类型在后面会讲到)。

每一个类型都会有一个潜在类型。如果这个类型是一个预定义类型(也就是基本类型),或者是一个由类型字面量构造的复合类型,那么它的潜在类型就是它自身。如string类型的潜在类型就是string类型,上面自定义的Person类型的潜在类型就是Person。如果一个类型并不属于上述情况,那么这个类型的潜在类型就是类型声明中的那个类型的潜在类型。

如下声明一个自定义类型

type MyString string1.
Copy after login

如上可以把类型MyString看作string类型的一个别名类型,那么MyString类型的潜在类型就是string类型。Go语言基本数据类型中的rune类型可以看作是uint32类型的一个别名类型,其潜在类型就是uint32。

注意:

  • 类型MyString和类型string是两个不相同的类型。不能将其中一个类型的值赋给另一个类型的变量。
  • 别名类型与它的源类型的不同仅仅体现在名称上,它们的内部结构是一致的;下面的类型转换的表达式都是合法的:MyString(“ABC”) 和string(MyString(“ABC”))。这种类型转换并不会创建新的值。

一个类型的潜在类型具有可传递性,如下:

type iString MyString1.
Copy after login

则类型isString的潜在类型就是string类型。

这里声明一个类型,如下:

type MyStrings [3]string1.
Copy after login

**Note:**The underlying type of type MyStrings is not [3]string. [3] string is neither a predefined type nor a composite type constructed from type literals, but an array type whose element type is string.

According to the above definition, it can be seen that the potential type of type MyStrings is the potential type string of [3]string.

The Go language stipulates that the potential type of an array type determines which type of elements can be stored in a variable of that type.

5. Operators

Operators are symbols used to perform specific arithmetic operations or logical operations. (I won’t explain it in detail here, it is similar to the operators in C language), but there is no ternary operator in Go language, so except for unary operators, all operators must be binary operators. Go language has a total of 21 operators, including arithmetic operators, comparison operators, logical operators, address operators and reception operators.

CategoryKeywords
Program Statement import, package
##&&Logic and operation. Binary, logical operator true && false //The expression result is false==Equality judgment operation. Binary, comparison operator "abc" == "abc" //The result is true!=Unequal judgment operation. Binary, comparison operator"abc" != "Abc" //The result is true##<<=>>=-\^11//The result is 14 (*/ %<<##>>Bitwise right shift operation, binary, arithmetic operator4 >> 2 //The result of the expression is 1Bitwise AND operation, unary, binary, arithmetic, addressBitwise clear operation, binary, arithmetic operator logical Non-operation, unary, logical operator##<-Receive operation, Unary, receiving operator<- ch

注意:假设上面的ch 代表了元素类型为 byte的通道类型值,则<- ch表示从ch中接收byte类型值的操作。

重点讲解3个操作符

1、&^ 实现了按位清除操作,按位清除就是根据第二个操作数的二进制值对第一个操作数的二进制值进行相应的清零操作,如果第二个操作数的某个二进制位上的数组为1,就把第一个操作数的对应二进制位上的数值设置为0。否则,第一个操作数的对应二进制位上的数值不变。这样的操作并不会改变第一个操作数的原值,只会根据两个操作数的二进制值计算出结果值。这样就可以理解上面的5 &^ 11的结果为4了。

2、^ 作为一元操作符,分两种情况:

(1). 操作数是无符号的整数类型,使用这一个操作就相当于对这个操作数和其整数类型的最大值进行二元的按位异或操作,如下:

^uint8(1)           = 254     
//无符号整数的一元按位异或操作00000001 ^ 11111111 = 11111110//对应的二进制数运算1.2.3.
Copy after login

如上,内置函数uint8会将一个整数字面量转换为一个uint8类型的值,这保证了一元操作符^的唯一操作数一定是一个无符号整数类型的值。

(2). 操作是有符号的整数类型,这一操作就相当于对这个操作数和-1进行二元按位异或操作。例如:

^1                  = -2 
//有符号整数的一元按位异或操作00000001 ^ 11111111 = 11111110//对应的二进制运算1.2.
Copy after login

**注意:**以上的操作数的二进制值都是以补码形式表示;默认情况下整数字面量是有符号的,所以(2)中操作数1不需要显示使用内置函数int8 。

3、<- 接收操作符,只作用于通道类型的值。使用时,需要注意两点:

(1). 从一个通道类型的空值(即nil)接收值的表达式将会永远被阻塞。
(2). 从一个已被关闭的通道类型值接收值会永远成功并立即返回一个其元素类型的零值。

一个由接收操作符和通道类型的操作数所组成的表达式可以直接被用于变量赋值或初始化,如下所示(在赋值语句讲解时,再细说)

v1 := <-ch
v2 = <-ch1.2.
Copy after login

特殊标记 = 用于将一个值赋给一个已被声明的变量或常量。
特殊标记 := 则用于在声明一个变量的同时对这个变量进行赋值,且只能在函数体内使用。

又如下:

v, ok = <-ch
v, ok := <-ch1.2.
Copy after login

当同时对两个变量进行赋值或初始化时,第二个变量将会是一个布尔类型的值。这个值代表了接收操作的成功与否。如果这个值为false,就说明这个通道已经被关闭了。(之后讲解通道类型会详细介绍)。

操作符优先级

SymbolDescriptionExample



is less than the judgment operation. Binary, comparison operator 1 < 2 //The expression result is true
is less than or equal to. Binary, comparison operator 1 <= 2 //The expression result is true
is greater than the judgment operation. Binary, comparison operator 3 > 2 //The expression result is true
is greater than or equal to. Binary, comparison operator 3 >= 2 //The expression result is true
means summation, one yuan is two Yuan, arithmetic operator 1 //The result is 1 (1 2) //The result is 3
represents the difference, one yuan It is binary again, arithmetic operator -1 //The result is -1 (1 – 2) //The result is -1
Bitwise OR operation, binary, arithmetic operator5 \ 11 //The result of the expression is 15
Press Bit XOR, one element is binary, arithmetic operator 55)//The result is -6
Product or value, one yuan, two binary, arithmetic, address*p //Value operation
Quotient operation, binary, arithmetic operator10 / 5 //The result of the expression is 2
Remainder operation, binary, arithmetic operator12 % 5 //The result of the expression is 2
Bitwise left shift operation, binary, arithmetic operator4 << 2 //The result of the expression is 16
##&
&v //Address operation&^
5 &^ 11 //The result of the expression is 4!
!b //If b is true, the result is false
优先级操作符
5* / % << >> & &^
4+ - \ ^
3== != < <= > >=
2&&
1

扩展知识:表达式

基本表达式

(1) 使用操作数来表示;

(2) 使用类型转换来表示;

(3) 使用内建函数调用来表示;

(4) 一个基本表达式和一个选择符号组成选择表达式;

例如,如果在一个结构体类型中存在字段f,我们就可以在这个结构体类型的变量x上应用一个选择符号来访问这个字段f,即x.f。其中,.f就是一个选择符号。注意:前提是这个变量x的值不能是nil。在Go语言中,nil用来表示空值。

(5) 一个基本表达式和一个索引符号组成索引表达式;

索引符号由狭义的表达式(仅由操作符和操作数组成)和外层的方括号组成,例如[]int{1,2,3,4,5}[2]就是索引表达式。
Go语言允许如下的赋值语句:

v, ok := a[x]1.
Copy after login

如上a为字典类型,x为字典的键。该索引表达式的结果是一对值,而不是单一值。第一个值的类型就是该字典类型的元素类型,而第二个值则是布尔类型。与变量ok绑定的布尔值代表了在字典类型a中是否包含了以x为键的键值对。如果在a中包含这样的键值对,那么赋给变量ok的值就是true,否则就为false。

**注意:**虽然当字典类型的变量a的值为nil时,求值表达式a[x]并不会发生任何错误,但是在这种情况下对a[x]进行赋值却会引起一个运行时恐慌( Go语言异常)。

(6) 一个基本表达式和一个切片符号组成切片表达式;

切片符号由2个或3个狭义的表达式和外层的方括号组成,这些表达式之间由冒号分隔。切片符号作用与索引符号类似,只不过索引符号针对的是一个点,切片符号针对的是一个范围。例如,要取出一个切片[]int{1,2,3,4,5}的第二个到第四个元素,那么可以使用切片符号的表达式[]int{1,2,3,4,5}[1:4],该结果还是一个切片。

切片表达式a[x:y:z],a是切片符号[x:y]的操作对象。其中,x代表了切片元素下界索引,y代表了切片的元素上界索引,而z则代表了切片的容量上界索引。约束如下:

0 <= 元素下界索引 <= 元素上界索引 <= 容量上界索引 <= 操作对象的容量

设a的值为[]int{1,2,3,4,5},则切片表达式a[:3]等同于a[0:3],这是因为切片符号的元素下界索引的默认值为0,相应的元素上界的索引的默认值为操作对象的长度值或容量值,即切片表达式a[3:]等同于a[3:5]。同样,切片表达式a[:]等同于复制a所代表的值并将这个复制品作为表达式的求值结果。

注意: UTF-8 编码格式会以3个字节来表示一个中文字符,而切片操作是针对字节进行的。

如果有“Go并发编程实战”的字符串类型的变量a,那么切片表达式a[1:3]的结果不是“o并”,而a[1:5]的结果才是“o并”。

(7) 一个基本表达式和一个类型断言符号组成;

类型断言符号以一个英文句号为前缀,并后跟一个被圆括号括起来的类型名称或类型字面量。类型断言符号用于判断一个变量或常量是否为一个预期的类型,并根据判断结果采取不同的响应。例如,如果要判断一个int8类型的变量num是否是int类型,可以这样编写表达式:interface{}(num).(int)。

对于一个求值结果为接口类型值的表达式x和一个类型T,对应的类型断言为:

x.(T)1.
Copy after login

该表达式的作用是判断“x不为nil且存储在其中的值是T类型的”是否成立。

如果T不是一个接口类型,那么x.(T)会判断类型T是否为x的动态类型(一个变量的动态类型就是在运行期间存储在其中的值的实际类型);而这个实际类型必须是该变量声明的那个类型的一个实现类型,否则就根本不可能在该变量中存储这一类型的值。所以类型T必须为x的类型的一个实现类型,而在Go语言中只有接口类型可以被其他类型实现,所以x的求值结果必须是一个接口类型的值。

所以上面表达式interface{}(num).(int)中表达式interface{}(num)的含义就是将变量num转换为interface{}类型的值(即它的结果值是接口类型的),而这刚好符合前面的定义。

知识点: interface{}是一个特殊的接口类型,代表空接口。所有类型都是它的实现类型。

在对变量的赋值或初始化的时候,也可以使用类型断言,如下:

v, ok := x.(T)1.
Copy after login

当使用类型断言表达式同时对两个变量进行赋值时,如果类型断言成功,那么赋给第一个变量的将会是已经被转换为T类型的表达式x的求值结果,否则赋给第一个变量的就是类型T的零值。布尔类型会被赋给变量ok,它体现了类型断言的成功(true)与否(false)。

注意: 在这种场景下,即使类型断言失败也不会引发运行时恐慌。

(8) 一个基本表达式和一个调用符号组成。

调用符号只针对于函数或者方法。与调用符号组合的基本表达式不是一个代表代码包名称(或者其别名)的标识符就是一个代表结构体类型的方法的名称的标识符。调用符号由一个英文句号为前缀和一个被圆括号括起来的参数列表组成,多个参数列表之间用逗号分隔。例如,基本表达式os.Open(“/etc/profile”)表示对代码包os中的函数Open的调用。

可变长参数

如果函数f可以接受的参数的数量是不固定的,那么函数f就是一个能够接受可变长参数的函数,简称可变参函数。在Go语言中,在可变参函数的参数列表的最后总会出现一个可变长参数,这个可变长参数的类型声明形如…T。Go语言会在每次调用函数f的时候创建一个切片类型值,并用它来存放这些实际函数。这个切片类型值的长度就是当前调用表达式中与可变长参数绑定的实际参数的数量。

可变参函数appendIfAbsent声明如下(函数体省略):

func appendIfAbsent(s []string, t ...string) []string1.
Copy after login

针对此函数的调用表达式如下:

appendIfAbsent([]string(“A”,”B”,”C”),”C”,”B”,”A”)1.
Copy after login

其中,与可变参数t绑定的切片类型值为[]string{”C”,”B”,”A”},包含了实际参数”C”,”B”和”A”。

也可以直接把一个元素类型为T的切片类型值赋给…T类型的可变长参数,如下调用:

appendIfAbsent([]string(“A”,”B”,”C”), []string(”C”,”B”,”A”)...)1.
Copy after login

或者如果有一个元素类型为stirng的切片类型的变量s的话,如下调用:

appendIfAbsent([]string(“A”,”B”,”C”), s...)1.
Copy after login

对于将切片类型的变量赋给可变长参数的情况,Go语言不会专门创建一个切片类型值来存储其中的实际参数。因为,这样的切片类型值已经存在了,可变长参数t的值就是变量s的值。

【相关推荐:Go视频教程编程教学

The above is the detailed content of There are several types of lexical elements in Go language. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template