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 程序的长度可以从 3 行到数百万行不等,应将其写入一个或多个扩展名为“.go”的文本文件中。例如,hello.go。
您可以使用“vi”、“vim”或任何其他文本编辑器将 Go 程序写入文件。
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 操作系统。
以下部分介绍如何在各种操作系统上安装 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 |
自由BSD | 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 | 导出 PATH = $PATH:/usr/local/go/bin |
苹果 | 导出 PATH = $PATH:/usr/local/go/bin |
自由BSD | 导出 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
输出
Hello, World!
Go - 程序结构
在学习 Go 编程语言的基本构建块之前,让我们首先讨论一下 Go 程序的最低限度结构,以便在后续章节中作为参考。
你好世界示例
Go 程序基本上由以下部分组成 -
- 包裹申报
- 导入包
- 功能
- 变量
- 陈述和表达式
- 评论
让我们看一个简单的代码,它将打印“Hello World”一词 -
package main import "fmt" func main() { /* This is my first sample program. */ fmt.Println("Hello, World!") }
让我们看一下上述程序的各个部分 -
程序 package main 的第一行定义了该程序所在的包名称。这是一个强制性的声明,因为 Go 程序在包中运行。主包是运行程序的起点。每个包都有一个与其关联的路径和名称。
下一行 import "fmt" 是一个预处理器命令,它告诉 Go 编译器包含 fmt 包中的文件。
下一行 func main() 是程序开始执行的主函数。
下一行 /*...*/ 会被编译器忽略,它用于在程序中添加注释。注释也使用 // 表示,类似于 Java 或 C++ 注释。
下一行 fmt.Println(...) 是 Go 中可用的另一个函数,它会导致消息“Hello, World!” 要显示在屏幕上。这里 fmt 包导出了 Println 方法,用于在屏幕上显示消息。
注意 Println 方法的大写 P。在Go语言中,如果名称以大写字母开头,则被导出。导出意味着函数或变量/常量可供相应包的导入者访问。
执行Go程序
让我们讨论如何将源代码保存在文件中,编译它,最后执行程序。请按照以下步骤操作 -
打开文本编辑器并添加上述代码。
将文件另存为hello.go
打开命令提示符。
转到保存文件的目录。
输入 go run hello.go并按 Enter 运行您的代码。
如果您的代码中没有错误,那么您将看到“Hello World!” 打印在屏幕上。
$ go run hello.go Hello, World!
确保 Go 编译器位于您的路径中,并且您正在包含源文件 hello.go 的目录中运行它。
Go - 基本语法
我们在上一章中讨论了 Go 程序的基本结构。现在很容易理解 Go 编程语言的其他基本构建块。
Go 中的代币
Go 程序由各种 token 组成。标记可以是关键字、标识符、常量、字符串文字或符号。例如,以下 Go 语句由六个标记组成 -
fmt.Println("Hello, World!")
各个令牌是 -
fmt . Println ( "Hello, World!" )
行分隔符
在 Go 程序中,行分隔符键是语句终止符。也就是说,各个语句不需要像“;”这样的特殊分隔符。在 C 语言中,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 是一种区分大小写的编程语言。因此,Manpower和manpower在 Go 中是两个不同的标识符。以下是可接受的标识符的一些示例 -
mahesh kumar abc move_name a_123 myname50 _temp j a23b9 retVal
关键词
下面的列表显示了 Go 中的保留字。这些保留字不得用作常量、变量或任何其他标识符名称。
休息 | 默认 | 功能 | 界面 | 选择 |
案件 | 推迟 | 去 | 地图 | 结构体 |
陈 | 别的 | 去 | 包裹 | 转变 |
常量 | 失败 | 如果 | 范围 | 类型 |
继续 | 为了 | 进口 | 返回 | 瓦尔 |
Go 中的空白
空白是 Go 中用来描述空白、制表符、换行符和注释的术语。仅包含空格(可能带有注释)的行称为空行,Go 编译器完全忽略它。
空格将语句的一部分与另一部分分隔开,并使编译器能够识别语句中一个元素(例如 int)的结束位置和下一个元素的开始位置。因此,在以下声明中 -
var age int;
int 和age 之间必须至少有一个空白字符(通常是空格),以便编译器能够区分它们。另一方面,在以下声明中 -
fruit = apples + oranges; // get the total fruit
水果和 = 之间或 = 和苹果之间不需要空格字符,但如果您希望出于可读性目的,可以自由地包含一些空格字符。
Go - 数据类型
在Go编程语言中,数据类型是指用于声明不同类型的变量或函数的广泛系统。变量的类型决定了它在存储中占用多少空间以及如何解释存储的位模式。
Go 中的类型可以分类如下 -
先生。 | 类型和描述 |
---|---|
1 | 布尔类型 它们是布尔类型,由两个预定义常量组成: (a) true (b) false |
2 | 数字类型 它们又是算术类型,并且在整个程序中表示 a) 整数类型或 b) 浮点值。 |
3 | 字符串类型 字符串类型表示字符串值的集合。它的值是一个字节序列。字符串是不可变类型,一旦创建,就不可能更改字符串的内容。预声明的字符串类型是string。 |
4 | 派生类型 它们包括 (a) 指针类型、(b) 数组类型、(c) 结构类型、(d) 联合类型和 (e) 函数类型 f) 切片类型 g) 接口类型 h) 映射类型 i) 通道类型 |
数组类型和结构类型统称为聚合类型。函数的类型指定具有相同参数和结果类型的所有函数的集合。我们将在下一节中讨论基本类型,而其他类型将在接下来的章节中介绍。
整数类型
预定义的独立于体系结构的整数类型是 -
先生。 | 类型和描述 |
---|---|
1 | uint8 无符号 8 位整数(0 到 255) |
2 | uint16 无符号 16 位整数(0 到 65535) |
3 | uint32 无符号 32 位整数(0 到 4294967295) |
4 | uint64 无符号 64 位整数(0 到 18446744073709551615) |
5 | 整型8 有符号 8 位整数(-128 到 127) |
6 | 整型16 有符号 16 位整数(-32768 到 32767) |
7 | 整型32 有符号 32 位整数(-2147483648 到 2147483647) |
8 | 整型64 有符号 64 位整数(-9223372036854775808 到 9223372036854775807) |
浮动类型
预定义的独立于体系结构的浮点类型是 -
先生。 | 类型和描述 |
---|---|
1 | 浮动32 IEEE-754 32 位浮点数 |
2 | 浮动64 IEEE-754 64 位浮点数 |
3 | 复杂64 具有 float32 实部和虚部的复数 |
4 | 复杂128 具有 float64 实部和虚部的复数 |
n 位整数的值是 n 位,并使用二进制补码算术运算来表示。
其他数字类型
还有一组具有特定于实现的大小的数字类型 -
先生。 | 类型和描述 |
---|---|
1 | 字节 与 uint8 相同 |
2 | 符文 与 int32 相同 |
3 | 单位 32 或 64 位 |
4 | 整数 与 uint 大小相同 |
5 | uintptr 一个无符号整数,用于存储指针值的未解释位 |
Go - 变量
变量只不过是程序可以操作的存储区域的名称。Go 中的每个变量都有一个特定的类型,它决定变量内存的大小和布局、该内存中可以存储的值的范围以及可以应用于该变量的操作集。
变量的名称可以由字母、数字和下划线字符组成。它必须以字母或下划线开头。大小写字母是不同的,因为 Go 区分大小写。基于上一章中解释的基本类型,将有以下基本变量类型 -
先生编号 | 类型和描述 |
---|---|
1 |
字节 通常是一个八位位组(一个字节)。这是一个字节类型。 |
2 |
整数 机器最自然的整数大小。 |
3 | 浮动32 单精度浮点值。 |
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;它指示编译器创建名为 i、j 和 k 的 int 类型变量。
变量可以在其声明中初始化(分配初始值)。变量的类型由编译器根据传递给它的值自动判断。初始化器由一个等号后跟一个常量表达式组成,如下所示 -
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) }
当上面的代码被编译并执行时,它会产生以下结果 -
20 x is of type float64
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) }
当上面的代码被编译并执行时,它会产生以下结果 -
20 42 x is of type float64 y is of type int
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) }
当上面的代码被编译并执行时,它会产生以下结果 -
3 4 foo a is of type int b is of type int c is of type string
Go 中的左值和右值
Go 有两种表达方式 -
左值- 引用内存位置的表达式称为“左值”表达式。左值可以显示为赋值的左侧或右侧。
右值- 术语右值是指存储在内存中某个地址的数据值。右值是一个不能赋值的表达式,这意味着右值可以出现在赋值的右侧,但不能出现在左侧。
变量是左值,因此可能出现在赋值的左侧。数字文字是右值,因此不能被赋值,也不能出现在左侧。
以下声明是有效的 -
x = 20.0
以下陈述无效。它会产生编译时错误 -
10 = 20
Go - 常量
常量是指程序在执行过程中不能改变的固定值。这些固定值也称为文字。
常量可以是任何基本数据类型,例如整型常量、浮点常量、字符常量或字符串常量。还有枚举常量。
常量的处理方式与常规变量一样,只是它们的值在定义后不能修改。
整数文字
整数文字可以是十进制、八进制或十六进制常量。前缀指定基数或基数:0x 或 0X 表示十六进制,0 表示八进制,没有任何内容表示十进制。
整数文字还可以具有 U 和 L 的组合后缀,分别表示无符号和长整型。后缀可以是大写或小写,并且可以是任何顺序。
以下是整数文字的一些示例 -
212 /* Legal */ 215u /* Legal */ 0xFeeL /* Legal */ 078 /* Illegal: 8 is not an octal digit */ 032UU /* Illegal: cannot repeat a suffix */
以下是各种类型整数文字的其他示例 -
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)、退格键等。这里有一些此类转义序列代码的列表 -
转义序列 | 意义 |
---|---|
\\ | \ 特点 |
\' | ' 特点 |
\" | “ 特点 |
\? | ?特点 |
\A | 警报或铃声 |
\b | 退格键 |
\F | 换页 |
\n | 新队 |
\r | 回车符 |
\t | 水平制表符 |
\v | 垂直标签 |
\呜呜 | 一到三位数的八进制数 |
\xhh 。。。 | 一位或多位数字的十六进制数 |
以下示例显示如何在程序中使用\t -
package main import "fmt" func main() { fmt.Printf("Hello\tWorld!") }
当上面的代码被编译并执行时,它会产生以下结果 -
Hello World!
Go 中的字符串文字
字符串文字或常量用双引号“”括起来。字符串包含与字符文字类似的字符:普通字符、转义序列和通用字符。
您可以使用字符串文字将长行分成多行,并使用空格分隔它们。
以下是字符串文字的一些示例。所有三种形式都是相同的字符串。
"hello, dear" "hello, \ dear" "hello, " "d" "ear"
const关键字_
您可以使用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) }
当上面的代码被编译并执行时,它会产生以下结果 -
value of area : 50
请注意,以大写字母定义常量是一种良好的编程习惯。
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 |
关系运算符
下表列出了Go语言支持的所有关系运算符。假设变量A为 10,变量B为 20,则 -
操作员 | 描述 | 例子 |
---|---|---|
== | 它检查两个操作数的值是否相等;如果是,则条件成立。 | (A == B) 不正确。 |
!= | 它检查两个操作数的值是否相等;如果值不相等,则条件成立。 | (A != B) 为真。 |
> | 检查左操作数的值是否大于右操作数的值;如果是,则条件成立。 | (A > B) 不正确。 |
< | 检查左操作数的值是否小于右操作数的值;如果是,则条件成立。 | (A < B) 为真。 |
>= | 它检查左操作数的值是否大于或等于右操作数的值;如果是,则条件成立。 | (A >= B) 不正确。 |
<= | 检查左操作数的值是否小于或等于右操作数的值;如果是,则条件成立。 | (A <= B) 为真。 |
逻辑运算符
下表列出了Go语言支持的所有逻辑运算符。假设变量A为 1,变量B为 0,则 -
操作员 | 描述 | 例子 |
---|---|---|
&& | 称为逻辑与运算符。如果两个操作数均非零,则条件为真。 | (A && B) 是错误的。 |
|| | 称为逻辑或运算符。如果两个操作数中的任何一个非零,则条件为真。 | (A || B) 为真。 |
! | 称为逻辑非运算符。用于反转其操作数的逻辑状态。如果条件为真,则逻辑 NOT 运算符将为假。 | !(A && B) 为真。 |
下表列出了Go语言支持的所有逻辑运算符。假设变量A为 true,变量B为 false,则 -
操作员 | 描述 | 例子 |
---|---|---|
&& | 称为逻辑与运算符。如果两个操作数都为假,则条件为假。 | (A && B) 是错误的。 |
|| | 称为逻辑或运算符。如果两个操作数中的任何一个为真,则条件为真。 | (A || B) 为真。 |
! | 称为逻辑非运算符。用于反转其操作数的逻辑状态。如果条件为真,则逻辑 NOT 运算符会将其设为假。 | !(A && B) 为真。 |
按位运算符
位运算符作用于位并执行逐位运算。&、| 和 ^ 的真值表如下 -
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 |
<< | 二进制左移运算符。左操作数的值向左移动右操作数指定的位数。 | A << 2 将给出 240,即 1111 0000 |
>> | 二进制右移运算符。左操作数的值向右移动右操作数指定的位数。 | A >> 2 将得到 15,即 0000 1111 |
赋值运算符
下表列出了 Go 语言支持的所有赋值运算符 -
操作员 | 描述 | 例子 |
---|---|---|
= | 简单赋值运算符,将右侧操作数的值分配给左侧操作数 | C = A + B 将 A + B 的值赋给 C |
+= | 添加AND赋值运算符,它将右操作数添加到左操作数并将结果分配给左操作数 | C += A 等价于 C = C + A |
-= | 减法AND赋值运算符,它从左操作数中减去右操作数,并将结果赋给左操作数 | C -= A 相当于 C = C - A |
*= | 乘法与赋值运算符,将右操作数与左操作数相乘,并将结果赋给左操作数 | C *= A 相当于 C = C * A |
/= | 除法与赋值运算符,它将左操作数与右操作数相除,并将结果赋给左操作数 | C /= A 相当于 C = C / A |
%= | 模数与赋值运算符,它使用两个操作数取模并将结果分配给左操作数 | C %= A 相当于 C = C % A |
<<= | 左移 AND 赋值运算符 | C <<= 2 与 C = C << 2 相同 |
>>= | 右移 AND 赋值运算符 | C >>= 2 与 C = C >> 2 相同 |
&= | 按位与赋值运算符 | C &= 2 与 C = C & 2 相同 |
^= | 按位异或和赋值运算符 | C ^= 2 与 C = C ^ 2 相同 |
|= | 按位 OR 和赋值运算符 | C |= 2 与 C = C | 相同 2 |
杂项运算符
Go 语言还支持其他一些重要的运算符,包括sizeof和?:。
操作员 | 描述 | 例子 |
---|---|---|
& | 返回变量的地址。 | &A; 提供变量的实际地址。 |
* | 指向变量的指针。 | *A; 提供指向变量的指针。 |
Go 中的运算符优先级
运算符优先级决定表达式中术语的分组。这会影响表达式的计算方式。某些运算符的优先级高于其他运算符;例如,乘法运算符的优先级高于加法运算符。
例如x = 7 + 3 * 2;此处,x 被分配为 13,而不是 20,因为运算符 * 的优先级高于 +,因此它首先乘以 3*2,然后添加到 7。
在这里,优先级最高的运算符出现在表的顶部,优先级最低的运算符出现在底部。在表达式中,将首先计算优先级较高的运算符。
类别 | 操作员 | 关联性 |
---|---|---|
后缀 | () [] -> . ++ - - | 左到右 |
一元 | + - ! ~ ++ - - (类型)* & sizeof | 右到左 |
乘法 | * / % | 左到右 |
添加剂 | + - | 左到右 |
转移 | <<>> | 左到右 |
关系型 | <<=>>= | 左到右 |
平等 | ==!= | 左到右 |
按位与 | & | 左到右 |
按位异或 | ^ | 左到右 |
按位或 | | | 左到右 |
逻辑与 | && | 左到右 |
逻辑或 | || | 左到右 |
任务 | = += -= *= /= %=>>= <<= &= ^= |= | 右到左 |
逗号 | , | 左到右 |
Go - 决策
决策结构要求程序员指定一个或多个要由程序评估或测试的条件,以及如果确定条件为真则要执行的一个或多个语句,以及可选地如果条件确定则要执行的其他语句确定为假。
以下是大多数编程语言中典型决策结构的一般形式 -
Go 编程语言提供以下类型的决策语句。单击以下链接查看其详细信息。
先生编号 | 声明及说明 |
---|---|
1 |
if 语句
if语句由一个布尔表达式后跟一个或多个语句组成。 |
2 | if...else 语句
if语句后面可以跟一个可选的else 语句,该语句在布尔表达式为 false 时执行。 |
3 |
嵌套 if 语句
您可以在另一个if或else if语句中使用一个if或else if语句。 |
4 |
switch语句
switch语句允许测试变量是否与值列表相等。 |
5 |
选择语句
select语句与switch语句类似,不同之处在于 case 语句指的是通道通信。 |
Go - 循环
可能存在一种情况,当您需要多次执行一段代码时。一般来说,语句是按顺序执行的:首先执行函数中的第一个语句,然后执行第二个语句,依此类推。
编程语言提供了各种控制结构,允许更复杂的执行路径。
循环语句允许我们多次执行一条语句或一组语句,以下是大多数编程语言中循环语句的一般形式 -
Go 编程语言提供了以下类型的循环来处理循环需求。
循环控制语句
循环控制语句改变执行的正常顺序。当执行离开其作用域时,在该作用域中创建的所有自动对象都将被销毁。
Go 支持以下控制语句 -
先生编号 | 控制语句和描述 |
---|---|
1 |
中断语句
它终止for 循环或switch语句,并将执行转移到紧跟在 for 循环或 switch 之后的语句。 |
2 |
继续声明
它使循环跳过其主体的其余部分并在重复之前立即重新测试其条件。 |
3 |
转到语句
它将控制权转移到带标签的语句。 |
无限循环
如果循环的条件永远不会变为假,则循环将成为无限循环。for 循环传统上用于此目的。由于形成 for 循环的三个表达式都不是必需的,因此您可以通过将条件表达式留空或向其传递 true 来创建无限循环。
package main import "fmt" func main() { for true { fmt.Printf("This loop will run forever.\n"); } }
当条件表达式不存在时,假定为真。您可能有一个初始化和增量表达式,但 C 程序员更常用 for(;;) 构造来表示无限循环。
注意- 您可以通过按 Ctrl + C 键终止无限循环。
Go - 函数
函数是一组共同执行任务的语句。每个 Go 程序都至少有一个函数,那就是main()。您可以将代码划分为单独的函数。如何在不同的函数之间划分代码取决于您,但从逻辑上讲,划分应该使每个函数执行特定的任务。
函数声明告诉编译器有关函数名称、返回类型和参数的信息。函数定义提供了函数的实际主体。
Go 标准库提供了许多您的程序可以调用的内置函数。例如,函数len()接受各种类型的参数并返回类型的长度。如果将字符串传递给它,该函数将返回字符串的长度(以字节为单位)。如果将数组传递给它,该函数将返回数组的长度。
函数也称为方法、子例程或过程。
定义函数
Go 编程语言中函数定义的一般形式如下 -
func function_name( [parameter list] ) [return_types] { body of the function }
Go 编程语言中的函数定义由函数头和函数体组成。这是函数的所有部分 -
Func - 它开始函数的声明。
函数名称- 这是函数的实际名称。函数名和参数列表共同构成函数签名。
参数- 参数就像占位符。当调用函数时,您将一个值传递给参数。该值称为实际参数或参数。参数列表是指函数参数的类型、顺序和数量。参数可选;也就是说,函数可以不包含参数。
返回类型- 函数可以返回值列表。return_types 是函数返回值的数据类型列表。有些函数执行所需的操作而不返回值。在这种情况下,return_type 不是必需的。
函数体- 它包含定义函数功能的语句集合。
例子
以下源代码显示了一个名为max()的函数。该函数采用两个参数 num1 和 num2 并返回两者之间的最大值 -
/* function returning the max between two numbers */ func max(num1, num2 int) int { /* local variable declaration */ result int if (num1 > num2) { result = num1 } else { result = num2 } return result }
调用函数
创建 Go 函数时,您需要定义该函数必须执行的操作。要使用函数,您必须调用该函数来执行定义的任务。
当程序调用函数时,程序控制权转移给被调用的函数。被调用函数执行已定义的任务,当执行其返回语句或到达其函数结束右大括号时,它将程序控制权返回给主程序。
要调用函数,您只需传递所需的参数及其函数名称即可。如果函数返回一个值,那么您可以存储返回的值。例如 -
package main import "fmt" func main() { /* local variable definition */ var a int = 100 var b int = 200 var ret int /* calling a function to get max value */ ret = max(a, b) fmt.Printf( "Max value is : %d\n", ret ) } /* function returning the max between two numbers */ func max(num1, num2 int) int { /* local variable declaration */ var result int if (num1 > num2) { result = num1 } else { result = num2 } return result }
我们保留了 max() 函数和 main() 函数并编译了源代码。运行最终的可执行文件时,它将产生以下结果 -
Max value is : 200
从函数返回多个值
Go 函数可以返回多个值。例如 -
package main import "fmt" func swap(x, y string) (string, string) { return y, x } func main() { a, b := swap("Mahesh", "Kumar") fmt.Println(a, b) }
当上面的代码被编译并执行时,它会产生以下结果 -
Kumar Mahesh
函数参数
如果函数要使用参数,则它必须声明接受参数值的变量。这些变量称为函数的形式参数。
形式参数的Behave与函数内的其他局部变量类似,在进入函数时创建并在退出时销毁。
调用函数时,可以通过两种方式将参数传递给函数 -
先生编号 | 呼叫类型和描述 |
---|---|
1 |
按值调用
此方法将参数的实际值复制到函数的形式参数中。在这种情况下,对函数内部参数所做的更改不会对参数产生影响。 |
2 |
通过参考调用
此方法将参数的地址复制到形式参数中。在函数内部,地址用于访问调用中使用的实际参数。这意味着对参数所做的更改会影响参数。 |
默认情况下,Go 使用按值调用来传递参数。一般来说,这意味着函数内的代码不能更改用于调用该函数的参数。上面的程序在调用max()函数时,使用了相同的方法。
功能使用
函数可以通过以下方式使用:
Go - 范围规则
任何编程中的作用域都是程序的一个区域,其中定义的变量可以存在,超出该区域则无法访问该变量。在 Go 编程语言中可以在三个地方声明变量 -
在函数或块内(局部变量)
所有函数之外(全局变量)
在函数参数(形参)的定义中
让我们了解什么是局部变量和全局变量以及什么是形式参数。
局部变量
在函数或块内声明的变量称为局部变量。它们只能由该函数或代码块内的语句使用。局部变量对其自身之外的函数来说是未知的。以下示例使用局部变量。这里所有变量 a、b 和 c 都是 main() 函数的局部变量。
package main import "fmt" func main() { /* local variable declaration */ var a, b, c int /* actual initialization */ a = 10 b = 20 c = a + b fmt.Printf ("value of a = %d, b = %d and c = %d\n", a, b, c) }
当上面的代码被编译并执行时,它会产生以下结果 -
value of a = 10, b = 20 and c = 30
全局变量
全局变量在函数外部定义,通常在程序顶部。全局变量在程序的整个生命周期中保持其值,并且可以在为程序定义的任何函数内访问它们。
全局变量可以被任何函数访问。也就是说,全局变量在声明后即可在整个程序中使用。以下示例同时使用全局变量和局部变量 -
package main import "fmt" /* global variable declaration */ var g int func main() { /* local variable declaration */ var a, b int /* actual initialization */ a = 10 b = 20 g = a + b fmt.Printf("value of a = %d, b = %d and g = %d\n", a, b, g) }
当上面的代码被编译并执行时,它会产生以下结果 -
value of a = 10, b = 20 and g = 30
程序中的局部变量和全局变量可以具有相同的名称,但函数内的局部变量的值优先。例如 -
package main import "fmt" /* global variable declaration */ var g int = 20 func main() { /* local variable declaration */ var g int = 10 fmt.Printf ("value of g = %d\n", g) }
当上面的代码被编译并执行时,它会产生以下结果 -
value of g = 10
形式参数
形式参数被视为该函数内的局部变量,并且它们优先于全局变量。例如 -
package main import "fmt" /* global variable declaration */ var a int = 20; func main() { /* local variable declaration in main function */ var a int = 10 var b int = 20 var c int = 0 fmt.Printf("value of a in main() = %d\n", a); c = sum( a, b); fmt.Printf("value of c in main() = %d\n", c); } /* function to add two integers */ func sum(a, b int) int { fmt.Printf("value of a in sum() = %d\n", a); fmt.Printf("value of b in sum() = %d\n", b); return a + b; }
当上面的代码被编译并执行时,它会产生以下结果 -
value of a in main() = 10 value of a in sum() = 10 value of b in sum() = 20 value of c in main() = 30
初始化局部和全局变量
局部变量和全局变量被初始化为其默认值,即 0;而指针则初始化为 nil。
数据类型 | 初始默认值 |
---|---|
整数 | 0 |
浮动32 | 0 |
指针 | 零 |
Go - 字符串
字符串在 Go 编程中广泛使用,是只读的字节切片。在 Go 编程语言中,字符串是切片。Go平台提供了各种库来操作字符串。
- 统一码
- 正则表达式
- 字符串
创建字符串
创建字符串最直接的方法是编写 -
var greeting = "Hello world!"
每当在代码中遇到字符串文字时,编译器都会创建一个字符串对象,其值在本例中为“Hello world!”。
字符串文字包含称为 runes 的有效 UTF-8 序列。字符串保存任意字节。
package main import "fmt" func main() { var greeting = "Hello world!" fmt.Printf("normal string: ") fmt.Printf("%s", greeting) fmt.Printf("\n") fmt.Printf("hex bytes: ") for i := 0; i < len(greeting); i++ { fmt.Printf("%x ", greeting[i]) } fmt.Printf("\n") const sampleText = "\xbd\xb2\x3d\xbc\x20\xe2\x8c\x98" /*q flag escapes unprintable characters, with + flag it escapses non-ascii characters as well to make output unambigous */ fmt.Printf("quoted string: ") fmt.Printf("%+q", sampleText) fmt.Printf("\n") }
这将产生以下结果 -
normal string: Hello world! hex bytes: 48 65 6c 6c 6f 20 77 6f 72 6c 64 21 quoted string: "\xbd\xb2=\xbc \u2318"
注意- 字符串文字是不可变的,因此一旦创建字符串文字就无法更改。
字符串长度
len(str) 方法返回字符串文字中包含的字节数。
package main import "fmt" func main() { var greeting = "Hello world!" fmt.Printf("String Length is: ") fmt.Println(len(greeting)) }
这将产生以下结果 -
String Length is : 12
连接字符串
strings 包包含一个用于连接多个字符串的方法join -
strings.Join(sample, " ")
连接将数组的元素连接起来以创建单个字符串。第二个参数是分隔符,放置在数组元素之间。
让我们看下面的例子 -
package main import ("fmt" "math" )"fmt" "strings") func main() { greetings := []string{"Hello","world!"} fmt.Println(strings.Join(greetings, " ")) }
这将产生以下结果 -
Hello world!
Go - 数组
Go编程语言提供了一种称为数组的数据结构,它可以存储相同类型元素的固定大小的顺序集合。数组用于存储数据的集合,但将数组视为相同类型的变量的集合通常更有用。
您可以声明一个数组变量(例如numbers)并使用numbers[0]、numbers[1] 和...、numbers[99] 来表示,而不是声明单个变量(例如number0、number1、...和number99)。