Go基础技术
Go - 开篇
Go语言是Robert Griesemer,Rob Pike和Ken Thompson于2007年在Google最初开发的一种编程语言。它是一种静态类型的语言,具有与C相似的语法。它提供了垃圾回收,类型安全,动态键入功能以及许多高级内置类型,例如可变长度数组和键值映射。它还提供了丰富的标准库。Go编程语言于2009年11月发布,并在Google的某些生产系统中使用。
适合人群
本教程是为需要从头了解Go编程语言的软件程序员设计的。本教程将使您对Go编程语言有足够的了解,从那里您可以进入更高的专业知识水平。
先决条件
在继续本教程之前,您应该对计算机编程术语有基本的了解。如果您对C有很好的命令,那么您很容易理解Go编程的概念并在学习道路上快速前进。
Go - 概述
Go是一种通用语言,设计时考虑了系统编程。它最初由Robert Griesemer,Rob Pike和Ken Thompson于2007年在Google开发。它是强类型和静态类型的,为垃圾回收提供内置支持,并支持并发编程。
程序是使用软件包构建的,用于高效地管理依赖关系。Go编程实现使用传统的编译和链接模型来生成可执行二进制文件。Go编程语言于2009年11月发布,已在Google的某些生产系统中使用。
Go编程的特点
下面列出了Go编程的最重要功能-
-
支持类似于动态语言的环境采用模式。例如,类型推断(x:= 0是int类型的变量x的有效声明)
-
编译时间很快。
-
内置的并发支持:轻量级进程(通过go例程),通道,select语句。
-
Go程序简单,简洁,安全。
-
支持接口和类型嵌入。
-
产生静态链接的本机二进制文件,而无需外部依赖。
有意排除的功能
为了使语言简洁明了,Go中省略了其他类似语言中常见的以下功能-
-
支持类型继承
-
支持方法或运算符重载
-
支持包之间的循环依赖
-
支持指针运算
-
支持断言
-
支持通用编程
Go程序
Go程序的长度可以从3行到数百万行不等,应将其写入一个或多个扩展名为“ .go”的文本文件中。例如,hello.go。
您可以使用“ vi”,“ vim”或任何其他文本编辑器将Go程序写入文件。
Go - 环境设置
本地环境设置
如果您仍然愿意为Go编程语言设置环境,则需要在计算机上使用以下两个软件-
- 文字编辑器
- 去编译器
文本编辑器
您将需要文本编辑器来键入程序。文本编辑器的示例包括Windows记事本,OS Edit命令,Brief,Epsilon,EMACS和vim或vi。
文本编辑器的名称和版本在不同的操作系统上可能会有所不同。例如,在Windows上使用记事本,在Windows以及Linux或UNIX上使用vim或vi。
使用文本编辑器创建的文件称为源文件。它们包含程序源代码。Go程序的源文件通常以扩展名“ .go”命名。
在开始编程之前,请确保已安装文本编辑器,并且您有足够的经验来编写计算机程序,将其保存在文件中,进行编译并最终执行它。
Go编译器
编写在源文件中的源代码是程序的可读源。需要对其进行编译并转换为机器语言,以便您的CPU可以根据给出的指令实际执行该程序。Go编程语言编译器将源代码编译成最终的可执行程序。
Go发行版是针对FreeBSD(版本8及更高版本),Linux,Mac OS X(Snow Leopard及更高版本)以及具有32位(386)和64位(amd64)x86处理器体系结构的Windows操作系统的二进制可安装版本。
以下部分说明了如何在各种OS上安装Go二进制发行版。
下载Go存档
从Go Downloads下载最新版本的Go可安装存档文件。本教程使用以下版本:go1.4.windows-amd64.msi。
它被复制到C:> go文件夹中。
操作系统 | 档案名称 |
---|---|
Windows | go1.4.windows-amd64.msi |
Linux | go1.4.linux-amd64.tar.gz |
苹果电脑 | go1.4.darwin-amd64-osx10.8.pkg |
FreeBSD | go1.4.freebsd-amd64.tar.gz |
在UNIX / Linux / Mac OS X和FreeBSD上安装
将下载档案解压缩到/ usr / local文件夹中,在/ usr / local / go中创建Go树。例如-
tar -C / usr / local -xzf go1.4.linux-amd64.tar.gz
将/ usr / local / go / bin添加到PATH环境变量中。
操作系统 | 输出量 |
---|---|
Linux | export PATH = $ PATH:/ usr / local / go / bin |
苹果电脑 | export PATH = $ PATH:/ usr / local / go / bin |
FreeBSD | export PATH = $ PATH:/ usr / local / go / bin |
在Windows上安装
使用MSI文件并按照提示安装Go工具。默认情况下,安装程序使用c:\ Go中的Go发行版。安装程序应在Window的PATH环境变量中设置c:\ Go \ bin目录。重新启动所有打开的命令提示符,以使更改生效。
验证安装
在C:> Go_WorkSpace中创建一个名为test.go的go文件。
文件:test.go
package main
import "fmt"
func main() {
fmt.Println("Hello, World!")
}
现在运行test.go以查看结果-
C:\Go_WorkSpace>go run test.go
Go - 程序结构
在研究Go编程语言的基本构建块之前,让我们首先讨论Go程序的最基本的结构,以便在以后的章节中作为参考。
你好世界的例子
Go程序基本上由以下部分组成-
- 包装声明
- 进口包装
- 功能
- 变数
- 陈述与表达
- 注释
让我们看一个简单的代码,该代码将显示“ Hello World”字样-
package main
import "fmt"
func main() {
/* This is my first sample program. */
fmt.Println("Hello, World!")
}
让我们看一下上述程序的各个部分-
-
程序包main的第一行定义了该程序应位于的包名称。这是强制性声明,因为Go程序在程序包中运行。主程序包是运行程序的起点。每个软件包都有与之关联的路径和名称。
-
下一行导入“ fmt”是一个预处理程序命令,该命令告诉Go编译器包括位于fmt包中的文件。
-
下一行func main()是程序执行开始的主要功能。
-
下一行/.../被编译器忽略,可以在程序中添加注释。注释也使用//表示,类似于Java或C ++注释。
-
下一行fmt.Println(...)是Go中可用的另一个函数,该函数导致消息“ Hello,World!”。在屏幕上显示。在这里,fmt包已导出了Println方法,该方法用于在屏幕上显示消息。
-
注意Println方法的大写字母P。在Go语言中,如果名称以大写字母开头,则会将其导出。导出意味着相应包的导入者可以访问该函数或变量/常量。
执行围棋程序
让我们讨论如何将源代码保存在文件中,对其进行编译并最终执行该程序。请按照下面给出的步骤-
-
打开一个文本编辑器并添加上述代码。
-
将文件另存为hello.go
-
打开命令提示符。
-
转到保存文件的目录。
-
输入go run hello.go,然后按Enter键运行代码。
-
如果您的代码没有错误,那么您将看到“ Hello World!”。打印在屏幕上。
$ go run hello.go
Hello, World!
确保Go编译器在您的路径中,并且正在包含源文件hello.go的目录中运行它。
Go - 基本语法
在上一章中,我们讨论了Go程序的基本结构。现在,您将很容易理解Go编程语言的其他基本构建块。
Go中的令牌
Go程序由各种令牌组成。令牌可以是关键字,标识符,常量,字符串文字或符号。例如,以下Go语句包含六个标记-
fmt.Println("Hello, World!")
各个令牌是-
fmt
.
Println
(
"Hello, World!"
)
分线器
在Go程序中,行分隔符键是语句终止符。也就是说,单个语句不需要像“;”这样的特殊分隔符。Go编译器在内部放置“;” 作为表示一个逻辑实体结束的语句终止符。
例如,看看以下语句-
fmt.Println("Hello, World!")
fmt.Println("I am in Go Programming World!")
注释
注释就像帮助Go程序中的文本,编译器会忽略它们。它们以/ 开头并以字符 /结束,如下所示-
/* my first program in Go */
您不能在注释中包含注释,并且它们也不会出现在字符串或字符文字中。
身份标识
Go标识符是用于标识变量,函数或任何其他用户定义项的名称。标识符以字母A到Z或a到z或下划线_开头,后跟零个或多个字母,下划线和数字(0到9)。
标识符=字母{字母| unicode_digit}。
Go不允许在标识符内使用标点符号,例如@,$和%。Go是区分大小写的编程语言。因此,人力和人力是Go中两个不同的标识符。这是可接受的标识符的一些示例-
mahesh kumar abc move_name a_123
myname50 _temp j a23b9 retVal
关键词
以下列表显示了Go中的保留字。这些保留字不得用作常量或变量或任何其他标识符名称。
break | default | func | interface | select |
case | defer | Go | map | Struct |
chan | else | Goto | package | Switch |
const | fallthrough | if | range | Type |
continue | for | import | return | Var |
Go中的空白
空格是Go语言中用来描述空白,制表符,换行符和注释的术语。仅包含空格的行(可能带有注释)被称为空白行,而Go编译器完全忽略它。
空格将语句的一个部分与另一个分开,并使编译器能够识别语句中一个元素(例如int)在何处结束以及下一个元素在何处开始。因此,在以下语句中-
var age int;
int和age之间必须至少有一个空格字符(通常为空格),以便编译器能够区分它们。另一方面,在以下语句中-
fruit = apples + oranges; // get the total fruit
水果和=之间,或=和苹果之间,不需要空格字符,尽管出于可读性考虑,您可以自由地添加一些字符。
Go - 数据类型
在Go编程语言中,数据类型是指用于声明不同类型的变量或函数的扩展系统。变量的类型决定了它在存储中占据多少空间以及如何解释所存储的位模式。
Go中的类型可以分类如下-
序号 | 类型和说明 |
---|---|
1 |
Boolean类型 它们是布尔类型,由两个预定义常量组成(a)是(b)否 |
2 |
Numeric类型 它们还是算术类型,在整个程序中代表a)整数类型或b)浮点值。 |
3 |
String类型 字符串类型表示字符串值的集合。它的值是一个字节序列。字符串是一经创建的不可变类型,因此无法更改字符串的内容。预先声明的字符串类型为string。 |
4 |
Derived类型 它们包括(a)Pointer类型,(b)Array类型,(c)Structure类型,(d)Union类型和(e)Function类型f)Slice类型g)Interface类型h)Map类型i)Channel类型 |
数组类型和结构类型统称为集合类型。函数的类型指定具有相同参数和结果类型的所有函数的集合。我们将在下一节中讨论基本类型,而其他类型将在接下来的章节中介绍。
整数类型
预定义的与体系结构无关的整数类型是-
序号 | 类型和说明 |
---|---|
1 |
uint8 无符号8位整数(0到255) |
2 |
uint16 无符号16位整数(0到65535) |
3 |
uint32 无符号32位整数(0至4294967295) |
4 |
uint64 无符号64位整数(0到18446744073709551615) |
5 |
int8 带符号的8位整数(-128至127) |
6 |
int16 有符号16位整数(-32768至32767) |
7 |
int32 有符号的32位整数(-2147483648至2147483647) |
8 |
int64 带符号的64位整数(-9223372036854775808至9223372036854775807) |
浮动类型
预定义的与体系结构无关的浮点类型为-
序号 | 类型和说明 |
---|---|
1 |
float32 IEEE-754 32位浮点数 |
2 |
float64 IEEE-754 64位浮点数 |
3 |
complex64 带有float32实部和虚部的复数 |
4 |
complex128 带有float64实部和虚部的复数 |
n位整数的值是n位,并使用二进制的补码算术运算表示。
其他数值类型
还有一组具有特定于实现的大小的数字类型-
序号 | 类型和说明 |
---|---|
1 |
byte 与uint8相同 |
2 |
rune 与int32相同 |
3 |
uint 32或64位 |
4 |
int 与uint一样大小 |
5 |
uintptr 一个无符号整数,用于存储指针值的未解释位 |
Go - 变量
变量不过是赋予程序可以操作的存储区的名称。Go中的每个变量都有一个特定的类型,该类型确定变量的内存大小和布局,可以存储在该内存中的值的范围以及可以应用于该变量的一组操作。
变量的名称可以由字母,数字和下划线字符组成。它必须以字母或下划线开头。大写和小写字母是不同的,因为Go区分大小写。基于上一章介绍的基本类型,将有以下基本变量类型-
序号 | 类型与说明 |
---|---|
1 |
byte 通常是一个八位位组(一个字节)。这是一个字节类型。 |
2 |
int 机器最自然的整数大小。 |
3 |
float32 单精度浮点值。 |
Go编程语言还允许定义各种其他类型的变量,例如枚举,指针,数组,结构和联合,我们将在后续章节中进行讨论。在本章中,我们将仅关注基本变量类型。
Go中的变量定义
变量定义告诉编译器在何处以及为变量创建多少存储空间。变量定义指定一种数据类型,并包含一个或多个该类型变量的列表,如下所示:
var variable_list optional_data_type;
在这里,optional_data_type是有效的Go数据类型,包括byte,int,float32,complex64,boolean或任何用户定义的对象等,并且variable_list可以包含一个或多个用逗号分隔的标识符名称。一些有效的声明显示在这里-
var i, j, k int;
var c, ch byte;
var f, salary float32;
d = 42;
语句**“ var i,j,k;” **声明并定义变量i,j和k;它指示编译器创建名为int的i,j和k变量。
变量可以在其声明中进行初始化(分配初始值)。变量的类型由编译器根据传递给它的值自动判断。初始化程序由一个等号和一个常量表达式组成,如下所示:
variable_name = value;
例如,
d = 3, f = 5; // declaration of d and f. Here d and f are int
对于没有初始化程序的定义:具有静态存储持续时间的变量使用nil隐式初始化(所有字节的值均为0);所有其他变量的初始值为其数据类型的零值。
Go中的静态类型声明
静态类型变量声明为编译器提供了一个保证,该变量具有给定的类型和名称,以便编译器可以继续进行进一步的编译而无需变量的完整细节。变量声明仅在编译时具有其含义,编译器在链接程序时需要实际的变量声明。
例
请尝试以下示例,其中已使用类型声明变量并在主函数内部对其进行了初始化-
package main
import "fmt"
func main() {
var x float64
x = 20.0
fmt.Println(x)
fmt.Printf("x is of type %T\n", x)
}
Go中的动态类型声明/类型推断
动态类型变量声明要求编译器根据传递给它的值来解释变量的类型。编译器不需要变量就具有静态类型的必要条件。
例
请尝试以下示例,其中变量已声明为没有任何类型。注意,在类型推断的情况下,我们使用:=运算符初始化变量y,而x使用=运算符初始化。
package main
import "fmt"
func main() {
var x float64 = 20.0
y := 42
fmt.Println(x)
fmt.Println(y)
fmt.Printf("x is of type %T\n", x)
fmt.Printf("y is of type %T\n", y)
}
Go中的混合变量声明
可以使用类型推断一次性声明不同类型的变量。
例
package main
import "fmt"
func main() {
var a, b, c = 3, 4, "foo"
fmt.Println(a)
fmt.Println(b)
fmt.Println(c)
fmt.Printf("a is of type %T\n", a)
fmt.Printf("b is of type %T\n", b)
fmt.Printf("c is of type %T\n", c)
}
Go中的左值和右值
Go中有两种表达式-
-
lvalue-引用内存位置的表达式称为“ lvalue”表达式。左值可能显示为分配的左侧或右侧。
-
rvalue-术语“右值”是指存储在内存中某个地址处的数据值。一个右值是一个不能为其赋值的表达式,这意味着一个右值可能出现在赋值的右侧而不是左侧。
变量是左值,因此可能出现在赋值的左侧。数字文字是右值,因此可能无法赋值并且不能出现在左侧。
以下语句有效-
x = 20.0
以下语句无效。它将产生编译时错误-
10 = 20
Go-常数
常数是指程序在执行过程中不得更改的固定值。这些固定值也称为文字。
常量可以是任何基本数据类型,例如整数常量,浮点常量,字符常量或字符串文字。也有枚举常量。
常量与常规变量的处理方式相同,只不过其值在定义后无法修改。
整数字面量
整数文字可以是十进制,八进制或十六进制常量。前缀指定基数或基数:十六进制为0x或0X,八进制为0,十进制为0。
整数文字也可以具有后缀,该后缀是U和L的组合,分别表示无符号和长整数。后缀可以是大写或小写,并且可以是任何顺序。
这是整数文字的一些例子-
212 /* Legal */
215u /* Legal */
0xFeeL /* Legal */
078 /* Illegal: 8 is not an octal digit */
032UU /* Illegal: cannot repeat a suffix */
以下是各种类型的Integer文字的其他示例-
85 /* decimal */
0213 /* octal */
0x4b /* hexadecimal */
30 /* int */
30u /* unsigned int */
30l /* long */
30ul /* unsigned long */
浮点文字
浮点文字具有整数部分,小数点,小数部分和指数部分。您可以用十进制或指数形式表示浮点文字。
在使用小数形式表示时,必须包含小数点和/或指数,并且在使用指数形式表示时,必须包含整数和/或小数。有符号数由e或E引入。
这是浮点文字的一些示例-
3.14159 /* Legal */
314159E-5L /* Legal */
510E /* Illegal: incomplete exponent */
210f /* Illegal: no decimal or exponent */
.e55 /* Illegal: missing integer or fraction */
转义序列
当某些字符前面带有反斜杠时,它们在Go中将具有特殊含义。这些被称为转义序列代码,用于表示换行符(\ n),制表符(\ t),退格键等。在这里,您可以找到其中一些转义序列代码的列表-
转义序列 | 含义 |
---|---|
\ | \字符 |
' | 字符 |
" | 字符 |
\? | ?字符 |
\一个 | 警报或铃声 |
\ b | 退格键 |
\f | 换页 |
\ n | 新队 |
\ r | 回车 |
\ t | 水平标签 |
\ v | 垂直标签 |
\ ooo | 八到三位数字 |
\ xhh. . . | 十六进制的一位或多位数字 |
以下示例显示如何在程序中使用\ t-
package main
import "fmt"
func main() {
fmt.Printf("Hello\tWorld!")
}
Go中的字符串文字
字符串文字或常量用双引号“”括起来。字符串包含与字符文字相似的字符:纯字符,转义序列和通用字符。
您可以使用字符串文字将长行分成多行,并使用空格分隔它们。
这是字符串文字的一些示例。这三种形式都是相同的字符串。
"hello, dear"
"hello, \
dear"
"hello, " "d" "ear"
该常量关键字
您可以使用const前缀来声明具有特定类型的常量,如下所示-
const variable type = value;
以下示例显示如何使用const关键字-
package main
import "fmt"
func main() {
const LENGTH int = 10
const WIDTH int = 5
var area int
area = LENGTH * WIDTH
fmt.Printf("value of area : %d", area)
}
请注意,在CAPITALS中定义常量是一种良好的编程习惯。
Go - 操作符
运算符是一个符号,告诉编译器执行特定的数学或逻辑操作。Go语言包含丰富的内置运算符,并提供以下类型的运算符-
- 算术运算符
- 关系运算符
- 逻辑运算符
- 按位运算符
- 赋值运算符
- 杂项运算符
本教程逐一说明算术,关系,逻辑,按位,赋值和其他运算符。
算术运算符
下表显示了Go语言支持的所有算术运算符。假设变量A持有10,变量B持有20,则-
操作符 | 描述 | 例 |
---|---|---|
+ | 加两个操作数 | A + B = 30 |
-- | 从第一个减去第二个操作数 | A-B ->-10 |
* | 将两个操作数相乘 | A * B = 200 |
/ | 用分子除以分母。 | B / A -> 2 |
% | 模运算符;给出整数除法后的余数。 | B%A -> 0 |
++ | 增量运算符。它将整数值增加一。 | A ++ ->11 |
- | 递减运算符。它将整数值减一。 | A-- ->9 |
package main
import "fmt"
func main() {
var a int = 21
var b int = 10
var c int
c = a + b
fmt.Printf("Line 1 - Value of c is %d\n", c )
c = a - b
fmt.Printf("Line 2 - Value of c is %d\n", c )
c = a * b
fmt.Printf("Line 3 - Value of c is %d\n", c )
c = a / b
fmt.Printf("Line 4 - Value of c is %d\n", c )
c = a % b
fmt.Printf("Line 5 - Value of c is %d\n", c )
a++
fmt.Printf("Line 6 - Value of a is %d\n", a )
a--
fmt.Printf("Line 7 - Value of a is %d\n", a )
}
关系运算符
下表列出了Go语言支持的所有关系运算符。假设变量A持有10,变量B持有20,则-
操作符 | 描述 | 例 |
---|---|---|
== | 它检查两个操作数的值是否相等。如果是,则条件成立。 | (A== B)不正确。 |
!= | 它检查两个操作数的值是否相等。如果值不相等,则条件为真。 | (A!= B)为真。 |
> | 它检查左操作数的值是否大于右操作数的值;如果是,则条件成立。 | (A> B)不正确。 |
< | 它检查左操作数的值是否小于右操作数的值;如果是,则条件成立。 | (A <B)是正确的。 |
>= | 它检查左操作数的值是否大于或等于右操作数的值;如果是,则条件成立。 | (A> = B)不正确。 |
<= | 它检查左操作数的值是否小于或等于右操作数的值;如果是,则条件成立。 | (A <= B)是正确的。 |
package main
import "fmt"
func main() {
var a int = 21
var b int = 10
if( a == b ) {
fmt.Printf("Line 1 - a is equal to b\n" )
} else {
fmt.Printf("Line 1 - a is not equal to b\n" )
}
if ( a < b ) {
fmt.Printf("Line 2 - a is less than b\n" )
} else {
fmt.Printf("Line 2 - a is not less than b\n" )
}
if ( a > b ) {
fmt.Printf("Line 3 - a is greater than b\n" )
} else {
fmt.Printf("Line 3 - a is not greater than b\n" )
}
/* Lets change value of a and b */
a = 5
b = 20
if ( a <= b ) {
fmt.Printf("Line 4 - a is either less than or equal to b\n" )
}
if ( b >= a ) {
fmt.Printf("Line 5 - b is either greater than or equal to b\n" )
}
}
逻辑运算符
下表列出了Go语言支持的所有逻辑运算符。假设变量A保持1,变量B保持0,则-
操作符 | 描述 | 例 |
---|---|---|
&& | 称为逻辑AND运算符。如果两个操作数都不为零,则条件为true。 | (A && B)是错误的。 |
|| | 称为逻辑或运算符。如果两个操作数中的任何一个都不为零,则条件为true。 | (A || B)为真。 |
! | 称为逻辑非运算符。用于反转其操作数的逻辑状态。如果条件为真,则逻辑非运算符将为假。 | !(A && B)是对的。 |
package main
import "fmt"
func main() {
var a bool = true
var b bool = false
if ( a && b ) {
fmt.Printf("Line 1 - Condition is true\n" )
}
if ( a || b ) {
fmt.Printf("Line 2 - Condition is true\n" )
}
/* lets change the value of a and b */
a = false
b = true
if ( a && b ) {
fmt.Printf("Line 3 - Condition is true\n" )
} else {
fmt.Printf("Line 3 - Condition is not true\n" )
}
if ( !(a && b) ) {
fmt.Printf("Line 4 - Condition is true\n" )
}
}
下表显示了Go语言支持的所有逻辑运算符。假设变量A为真,变量B为假,则-
操作符 | 描述 | 例 |
---|---|---|
&& | 称为逻辑AND运算符。如果两个操作数均为假,则条件变为假。 | (A && B)是错误的。 |
|| | 称为逻辑或运算符。如果两个操作数中的任何一个为true,则条件为true。 | (A || B)为真。 |
! | 称为逻辑非运算符。用于反转其操作数的逻辑状态。如果条件为真,则逻辑非运算符会将其设置为假。 | !(A && B)是对的。 |
按位运算符
按位运算符对位进行运算并执行逐位运算。&,|和^的真值表如下-
p | q | p&q | p | q | p ^ q |
---|---|---|---|---|
0 | 0 | 0 | 0 | 0 |
0 | 1 | 0 | 1 | 1 |
1 | 1 | 1 | 1 | 0 |
1 | 0 | 0 | 1 | 1 |
假设A = 60;和B =13。以二进制格式,它们将如下所示-
A = 0011 1100
B = 0000 1101
A&B = 0000 1100
A | B = 0011 1101
A ^ B = 0011 0001
〜A = 1100 0011
下表列出了C语言支持的按位运算符。假设变量A保持60,变量B保持13,则-
操作符 | 描述 | 例 |
---|---|---|
& | 如果两个操作数中都存在二进制AND运算符,则会将一位复制到结果中。 | (A&B)将得到12,即0000 1100 |
| | 如果任一操作数中存在二进制或运算符,则会对其进行复制。 | (A | B)将得到61,即0011 1101 |
^ | 如果在一个操作数中设置了该位,但不是在两个操作数中都设置了位,则二进制XOR运算符将复制该位。 | (A ^ B)将得出49,即0011 0001 |
<< | 二进制左移运算符。左操作数的值向左移动右操作数指定的位数。 | << 2将得到240,即1111 0000 |
>> | 二进制右移运算符。左操作数的值向右移动右操作数指定的位数。 | A >> 2将得到15,即0000 1111 |
package main
import "fmt"
func main() {
var a uint = 60 /* 60 = 0011 1100 */
var b uint = 13 /* 13 = 0000 1101 */
var c uint = 0
c = a & b /* 12 = 0000 1100 */
fmt.Printf("Line 1 - Value of c is %d\n", c )
c = a | b /* 61 = 0011 1101 */
fmt.Printf("Line 2 - Value of c is %d\n", c )
c = a ^ b /* 49 = 0011 0001 */
fmt.Printf("Line 3 - Value of c is %d\n", c )
c = a << 2 /* 240 = 1111 0000 */
fmt.Printf("Line 4 - Value of c is %d\n", c )
c = a >> 2 /* 15 = 0000 1111 */
fmt.Printf("Line 5 - Value of c is %d\n", c )
}
赋值运算符
下表列出了Go语言支持的所有赋值运算符-
操作符 | 描述 | 例 |
---|---|---|
= | 简单的赋值运算符,将值从右侧操作数分配到左侧操作数 | C = A + B将A + B的值赋给C |
+= | 添加AND赋值运算符,将右操作数添加到左操作数,并将结果分配给左操作数 | C += A等于C = C + A |
-= | 减去AND赋值运算符,它从左操作数中减去右操作数,并将结果分配给左操作数 | C-= A等效于C = C-A |
*= | 将AND赋值运算符相乘,将右操作数与左操作数相乘并将结果分配给左操作数 | C *= A等效于C = C * A |
/= | 除法AND赋值运算符,它将左操作数除以右操作数,并将结果分配给左操作数 | C /= A等于C = C / A |
%= | 模AND赋值运算符,它使用两个操作数取模并将结果赋给左操作数 | C%= A等于C = C%A |
<<= | 左移AND赋值运算符 | C <<= 2与C = C << 2相同 |
>>= | 右移和赋值运算符 | C >>= 2与C = C >> 2相同 |
&= | 按位与赋值运算符 | C&= 2与C = C&2相同 |
^= | 按位异或和赋值运算符 | C ^= 2与C = C ^ 2相同 |
|= | 按位或运算符和赋值运算符 | C |= 2等于C = C | 2 |
package main
import "fmt"
func main() {
var a int = 21
var c int
c = a
fmt.Printf("Line 1 - = Operator Example, Value of c = %d\n", c )
c += a
fmt.Printf("Line 2 - += Operator Example, Value of c = %d\n", c )
c -= a
fmt.Printf("Line 3 - -= Operator Example, Value of c = %d\n", c )
c *= a
fmt.Printf("Line 4 - *= Operator Example, Value of c = %d\n", c )
c /= a
fmt.Printf("Line 5 - /= Operator Example, Value of c = %d\n", c )
c = 200;
c <<= 2
fmt.Printf("Line 6 - <<= Operator Example, Value of c = %d\n", c )
c >>= 2
fmt.Printf("Line 7 - >>= Operator Example, Value of c = %d\n", c )
c &= 2
fmt.Printf("Line 8 - &= Operator Example, Value of c = %d\n", c )
c ^= 2
fmt.Printf("Line 9 - ^= Operator Example, Value of c = %d\n", c )
c |= 2
fmt.Printf("Line 10 - |= Operator Example, Value of c = %d\n", c )
}
杂项运算符
Go语言还支持其他一些重要的运算符,包括sizeof和?:。
操作符 | 描述 | 例 |
---|---|---|
& | 返回变量的地址。 | &a; 提供变量的实际地址。 |
* | 指向变量的指针。 | *a; 提供指向变量的指针。 |
package main
import "fmt"
func main() {
var a int = 4
var b int32
var c float32
var ptr *int
/* example of type operator */
fmt.Printf("Line 1 - Type of variable a = %T\n", a );
fmt.Printf("Line 2 - Type of variable b = %T\n", b );
fmt.Printf("Line 3 - Type of variable c= %T\n", c );
/* example of & and * operators */
ptr = &a /* 'ptr' now contains the address of 'a'*/
fmt.Printf("value of a is %d\n", a);
fmt.Printf("*ptr is %d.\n", *ptr);
}
Go中的运算符优先级
运算符优先级确定表达式中术语的分组。这会影响表达式的求值方式。某些运算符具有更高的优先级;例如,乘法运算符的优先级高于加法运算符。
例如x = 7 + 3 * 2; 在这里,x被赋值为13,而不是20,因为运算符*的优先级比+高,因此它首先与3 * 2相乘,然后加到7。
在这里,优先级最高的运算符出现在表格的顶部,而优先级最低的运算符出现在表格的底部。在表达式中,优先级更高的运算符将首先被评估。
类别 | 操作员 | 关联性 |
---|---|---|
后缀 | ()[]->。++-- | 左到右 |
一元 | +-!〜++--(type)*&sizeof | 右到左 |
乘除 | * /% | 左到右 |
累计 | +- | 左到右 |
移动 | << >> | 左到右 |
关系型 | <<=>> = | 左到右 |
等于 | ==!= | 左到右 |
按位与 | 和 | 左到右 |
按位异或 | ^ | 左到右 |
按位或 | | | 左到右 |
逻辑与 | && | 左到右 |
逻辑或 | || | 左到右 |
赋值 | = +=-= *= /=%= >>= <<=&= ^= |= | 右到左 |
逗号 | , | 左到右 |
package main
import "fmt"
func main() {
var a int = 20
var b int = 10
var c int = 15
var d int = 5
var e int;
e = (a + b) * c / d; // ( 30 * 15 ) / 5
fmt.Printf("Value of (a + b) * c / d is : %d\n", e );
e = ((a + b) * c) / d; // (30 * 15 ) / 5
fmt.Printf("Value of ((a + b) * c) / d is : %d\n" , e );
e = (a + b) * (c / d); // (30) * (15/5)
fmt.Printf("Value of (a + b) * (c / d) is : %d\n", e );
e = a + (b * c) / d; // 20 + (150/5)
fmt.Printf("Value of a + (b * c) / d is : %d\n" , e );
}