我们日常玩的电脑游戏、手机上运行的各类软件、甚至是操作系统都是以数据的管理和计算为基础的,那么这些数据是如何在计算机中安家的呢?这就涉及到了编程语言中的基本语法内容了,这节课我们一起来看一下Go语言的基础语法。具体包括以下内容:
- 变量与常量
- 声明与赋值
- 基本数据类型
💡 提示: 为易于大家领会要点,节约篇幅,在文末有3个附录。大家可结合相应的知识点进行查阅和实践。
# 变量与常量
与大多数编程语言类似,Go语言支持声明变量与常量,Go语言程序在运行时,会把所需的数据加载到内存中,这些数据又分为常量和变量,它们的定义也很好理解:
- 常量是一个简单值的标识符,在程序运行时,不会被修改的量;
- 变量来源于数学,是计算机语言中能储存计算结果或能表示值的抽象概念,它的值通常是可变的。
为何要将数据分为可变的变量和不可变的常量?答案是:为了程序更快、更安全。
- 更快:虽然常量和变量都会占用内存,但它们位于不同的位置,常量会在编译后放在数据段内存;变量放在代码段内存。合理地使用常量将加快编译速度与减少运行时的内存占用。
- 更安全:由于常量不可变,因此我们就没有机会将其误改为其它的值。
变量与常量本身很好理解,这里就不过多解释了,需要注意的是它们的命名。
无论是常量还是变量,我们都可以通过它们的名字访问它们。Go语言中包含25个关键字和37个保留字(参考附录一),在起名字的时候要注意避开它们。
如果错误地使用了关键字或者保留字作为名字,编译器便无法区分到底该作为名字处理,还是当作本身的作用处理,因此会引发编译时错误。使用GoLand会帮助我们规避这类问题,例如下面的代码:
Go
复制代码//变量声明
var break = "打断"
由于break本身属于流程控制类的关键字,代码无法被编译。
在实际开发中,不同的开发者起名字的习惯不同,往往会导致代码的可读性降低甚至引起歧义。比如,把变量命名为a1、a2、a3……时间久了之后几乎没有人能一下子看懂它们代表什么含义,包括代码的作者。因此,一个好的习惯是尽量使用能表达其含义的一个或多个英文单词来命名。
- 对于变量,除了首个单词外,每个单词的首字母用大写表示,这种命名法通常被称为小驼峰式命名法;若所有单词的首字母均大写,则成为大驼峰式命名法(又被称为帕斯卡命名法)。由于变量有可见性(有关可见性的更多内容,将在结构体/包中介绍。)之分,对于对外可见的变量,使用大驼峰法;对于对外不可见的变量,使用小驼峰法。特别地,若变量/常量是布尔类型,最好以is、allow、has、can之类来开头;
- 对于常量,单词均用大写字母来表示,每个字母之间使用下划线来分割。
例如:
Go
复制代码//变量声明
var exampleNumberA int = 10
var isDarkMode bool = false
//常量声明
const WIDTH_OF_RECT int = 12
const ALLOW_DOWNLOAD_WHEN_WIFI bool = true
💡 提示: 本小册中的所有示例代码均按照上述规则对变量/常量命名。
❗️ 注意: Go语言是区分大小写的,exampleNumberA和ExampleNumberA是两个不同的变量。
Go语言中的命名规范除了体现在变量/常量的命名上,还体现在包名、源码文件名等多个方面,具体请参考文末附录二。
# 声明与赋值
从定义上看,声明是指:
当一个计算机程序需要调用内存空间时,对内存发出的“占位”指令,称为:“声明”。
通俗地讲,我们使用的软件都是从硬盘加载到内存,然后在内存中运行的,因为内存和CPU之间交换数据的速度更快。除了程序运行的逻辑外,必要的数据必然也会被加载到内存中。而声明的目的就是在计算机的内存中占用一定大小的空间,用来存放数据。
在Go语言中,变量或常量的数据类型必须先声明,才能使用,且无法将不相关的数据赋值给它们。
这是因为Go语言和Java、C、C++等语言一样,属于静态语言,静态语言具有更严谨的结构要求、调试便捷(可通过代码直观地看到数据类型)与确保类型安全(无法使用不同类型的数据赋值)的特点,必须要先做声明。而像PHP、Python、JavaScript等动态语言则没有这个限制。
从根本上说,静态类型和动态类型语言的最大区别就是,数据类型是否在编译时确定。
💡 提示: 如果想要计算机运行人类编写的Go语言代码,需要先编译再运行。程序代码易于人类编写和理解,但计算机无法直接理解,需要先“翻译”为机器语言才行,编译便是完成这个“翻译”工作的。与此相对,运行便是将机器语言加载到内存中执行的过程。
# 变量的声明与赋值
在Go语言中,声明变量的一般格式为:
Go
复制代码var name type
其中,var是声明变量的关键字,固定不变,表明意图——要声明一个变量;name紧随其后,是开发者自定义的变量名,可根据实际用途和命名规范命名;type表示该变量所属的数据类型。
完成声明后,便要对变量进行赋值了,否则它没有任何意义。赋值后,变量就有了“初始值”;对于已经有值的变量,再次赋值将使用新值覆盖旧值,达到修改的目的。
和大多数编程语言一样,使用等号“=”为变量或常量赋值。如:
Go
复制代码//声明一个名为number的变量,类型为int(整数类型)
var number int
//为number赋值
number = 100
如此,number这个变量就表示100这个整数了。此外,变量的声明和赋值还可一并完成,如:
Go
复制代码//变量声明
var number int = 100
这种写法与前一个示例作用相同。
# 常量的声明与赋值
常量声明和赋值的一般格式为:
Go
复制代码const name type = value
其中,const是声明常量的关键字,固定不变,表明意图,要声明一个常量;name和type的意义与声明变量时一样;value是常量的值。如:
Go
复制代码//声明一个名为PI的常量,类型为float64(浮点数类型)
const PI float64 = 3.14
❗️ 注意: 声明常量时,必须为其赋值,且后续无法修改。
# Go语言的类型推断
使用Go语言可简化代码,类型推断体现了这一点。当声明与赋值一并进行时,如果数据为Go内置的基础类型,则可无需指定类型。如:
Go
复制代码//变量声明
var number = 100
//常量声明
const PI = 3.14
无需担心,由于number的值为100,Go语言会推断出它的类型为整数型。同理,PI也会被推断为浮点数型。
对于变量,还有一种超级精简的声明和赋值方式,示例如下:
Go
复制代码//变量声明
number := 100
❗️ 注意: 冒号等于号“:=”的作用是声明和赋值,若number是已经声明过的变量,则无法使用 := 的方式赋值。
# 批量声明/赋值
为了方便多个变量/常量的声明和赋值,我们还可以批量处理它们,示例如下:
Go
复制代码//变量
var (
//声明+赋值
number int = 100
//声明+赋值(类型推断)
text = "Hello"
//只声明
name string
)
//常量
const (
// PI 声明+赋值
PI float64 = 3.14
// WIDTH 声明+赋值(类型推断)
WIDTH = 5
// HEIGHT 声明+赋值(类型推断)
HEIGHT = 10
)
到此,一些朋友可能会问:什么是常量/变量?为什么常量的值可以修改而变量不行?为何声明常量都用大写字符?除了示例中的int、float64、string,还有哪些内置类型……
带着这些疑问,我们继续往下看。
# 基本数据类型
和其它高级编程语言类似,Go语言同样内置了多种基本数据类型,它们也被称为内置数据类型。
除了基本数据类型之外,还有接口类型(下一讲中会介绍)和复合类型(可以简单地理解为基本数据的“组合体”,如数组、切片、结构体等)。
由此可见,掌握基本数据类型是实现复杂运算乃至构建复杂程序的基础,也是日常开发中使用最频繁的类型。
Go语言的基本数据类型包括数字型(含整数int系列、浮点数float系列和复数complex系列)、布尔型(bool)和字符串型(string)。对于数字型和布尔型较为易懂,在本讲前面的内容中已经使用过了,这里要特别强调字符串型。
对于字符串型值,我们通常在必要时使用一些转义字符,以实现文本的正确输出。
举例来说,如果我们想要使用单个变量表示下面的两行字:
汉语:"你好"的英文翻译是:"Hello" 汉语:"早上好"的英文翻译是:"Good Morning"
代码可写为:
Go
复制代码var text string = "汉语:\"你好\"的英文翻译是:\"Hello\"\n汉语:\"早上好\"的英文翻译是:\"Good Morning\""
fmt.Println(text)
这段代码中,使用了"输出英文双引号,\n用作换行。当然,若使用中文的双引号时无需使用转义的。更多转义字符及含义请参考附录四。
# 小结
🎉 恭喜,您完成了本次课程的学习!
📌 以下是本次课程的重点内容总结:
- 变量与常量
- 声明
- 基本数据类型
- 代码风格约定
我们使用的几乎所有软件的背后,其实都是数据,数据是构成程序的基础单位。Go语言将数据分为了常量与变量,分别表示不变的数据和可变的数据。程序运行后,数据被放到计算机内存中管理并参与运算。声明在内存中开辟空间,让数据在内存中“安家”。
为了增强代码的可读性和安全性,Go语言本身是静态语言,数据的类型在声明时便要指定。Go语言中的基本数据类型分为数值型、布尔型和字符串型。
为了便于理解和规范代码,为变量命名时,遵循“驼峰式命名法”,再根据可见性使用小驼峰和大驼峰式;为常量命名时,遵循全大写,单词之间使用下划线分割的方式命名。另外,源码文件名、包名等也有规范命名要求。
学习这一讲时,我特别建议大家动手实践,尤其对于编程0基础的同学来说,练习更为重要,切勿停留在理解层面。如果有问题的话,欢迎各位随时在微信群里发问。
➡️ 在下次课程中,我们会阐述如下内容:
- Go语言基础语法之流程控制结构,包括:
- 指针类型
- 运算符及优先级
- 类型转换
# 附录一 Go语言中的关键字和保留字
Go语言中的关键字
包管理 | 声明与定义 | 流程控制 |
---|---|---|
import、package | chan、const、func、interface、map、struct、type、var | break、case、continue、default、defer、else、fallthrough、for、go、goto、if、range、return、select |
Go语言中的保留字
常量 | 变量类型 | 内置函数名 |
---|---|---|
true、false、iota、nil | Int、int8、int16、int32、int64、uint、uint8、uint16、uint32、uint64、uintptr、float32、float64、complex128、complex64、bool、byte、rune、string、error | make、len、cap、new、append、copy、close、delete、complex、real、imag、panic、recover |
# 附录二 Go语言命名规范
Go语言中的命名规则应尽量使用能表达其含义或目的的一个或多个英文单词来命名。英文单词之间的连接方式和大小写规则如下:
# 源码文件名
英文单词全部小写,每个单词之间使用下划线分割。
如:hello_world.go、calc.go
# 包名
使用尽量简短的英文单词,全部小写,名称不要与Go内置标准库相同。
如:net、database
# 变量名
整体遵循驼峰式命名法。允许从外部访问的名字(类似Java中的public修饰符)以大写开头(大驼峰法,亦称帕斯卡命名法),不允许从外部访问的名字以小写开头(小驼峰法)。对于布尔类型的变量,可考虑添加Has、Is、Can、Allow前缀。
如:age、personStatus、StudentAge、isDarkMode
# 常量名
英文单词全部大写,每个单词之间使用下划线分割。对于布尔类型的变量,可考虑添加Has、Is、Can、Allow前缀。
如:SERVER_URL、IS_ALLOW_DOWNLOAD
# 结构体名
整体遵循驼峰式命名法。允许从外部访问的名字(类似Java中的public修饰符)以大写开头(大驼峰法,亦称帕斯卡命名法),不允许从外部访问的名字以小写开头(小驼峰法)。
如:personInfo := {"David", "18"}
使用struct关键字进行声明和初始化时,使用多行表示,每行表示一个成员。
如:
Go
复制代码type PersonInfo struct {
name string
age int
}
# 接口名
整体遵循驼峰式命名法。允许从外部访问的名字(类似Java中的public修饰符)以大写开头(大驼峰法,亦称帕斯卡命名法),不允许从外部访问的名字以小写开头(小驼峰法),通常以“er”结尾。
如:
Go
复制代码type DownloadListener interface {
DownloadStart() (err error)
DownloadInProgress() (err error)
DownloadComplete() (err error)
}
# 附录三 Go语言基本数据类型定义及精度
# 整数型
类型 | 精度 |
---|---|
uint8 | 无符号 8 位整型 (0 到 28-1) |
uint16 | 无符号 16 位整型 (0 到 216-1) |
uint32 | 无符号 32 位整型 (0 到 232-1) |
uint64 | 无符号 64 位整型 (0 到 264-1) |
int8 | 有符号 8 位整型 (-27 到 27-1) |
int16 | 有符号 16 位整型 (-215 到 215-1) |
int32 | 有符号 32 位整型 (-231 到 231) |
int64 | 有符号 64 位整型 (-264 到 264) |
# 浮点型
类型 | 精度 |
---|---|
float32 | ±1.18×10-38 到 ±3.4×1038 |
float64 | ±2.23×10-308 到 ±1.8×10308 |
# 复数型
类型 | 精度 |
---|---|
complex64 | 含 float32 位实数和 float32 位虚数 |
complex128 | 含 float64 位实数和 float64 位虚数 |
# 布尔型
类型 | 精度 |
---|---|
bool | true 或 false |
# 字符串型
类型 | 精度 |
---|---|
string | UTF-8 编码标识的 Unicode 文本 |