Go 语言基础语法
思维导图预习
命名
命名规则
Go 语言中的函数名、变量名、常量名、类型名、语句标号和包名等所有的命名,都遵循一个简单的命名规则:
一个标识符必须以一个字母(Unicode字母)或下划线开头,后面可以跟任意数量的字母、数字或下划线。
关键字
Go语言中关键字有25个;关键字不能用于自定义标识符,只能在特定语法结构中使用。
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
预定义标识符
参考资料:
有大约 30 多个预定义的标识符,比如 int 和 true 等,主要对应内建的常量、类型和函数。
这些内部预先定义的名字并不是关键字,你可以在定义中重新使用它们。
内建常量: 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
标识符可见范围
如果一个名字是在函数内部定义,那么它就只在函数内部有效。如果是在函数外部定义,那么将在当前包的所有文件中都可以访问。
名字的开头字母的大小写决定了名字在包外的可见性。如果一个名字是大写字母开头的,那么它将是导出的,也就是说可以被外部的包访问。
声明
声明语句定义了程序的各种实体对象以及部分或全部的属性。
- var:变量声明
- const:常量声明
- type:类型声明
- func:函数实体对象声明
变量
var 声明语句
var 声明语句可以创建一个特定类型的变量,然后给变量附加一个名字,并且设置变量的初始值。变量声明的一般语法如下:
var 变量名字 类型 = 表达式
简短变量声明
在函数内部,有一种称为简短变量声明语句的形式可用于声明和初始化局部变量。它以“名字 := 表达式”形式声明变量,变量的类型根据表达式来自动推导。
因为简洁和灵活的特点,简短变量声明被广泛用于大部分的局部变量的声明和初始化。var 形式的声明语句往往是用于需要显式指定变量类型的地方,或者因为变量稍后会被重新赋值而初始值无关紧要的地方。
i := 100 // an int
var boiling float64 = 100 // a float64
变量的生命周期
变量的生命周期指的是在程序运行期间变量有效存在的时间段。
- 对于在包一级声明的变量来说,它们的生命周期和整个程序的运行周期是一致的。
- 局部变量的生命周期则是动态的:每次从创建一个新变量的声明语句开始,直到该变量不再被引用为止,然后变量的存储空间可能被回收。
函数的参数变量和返回值变量都是局部变量。它们在函数每次被调用的时候创建。
赋值
使用赋值语句可以更新一个变量的值,最简单的赋值语句是将要被赋值的变量放在 =
的左边,新值的表达式放在 =
的右边。
x = 1 // 命名变量的赋值
*p = true // 通过指针间接赋值
person.name = "bob" // 结构体字段赋值
count[x] = count[x] * scale // 数组、slice或map的元素赋值
空白标识符
和变量声明一样,我们可以用下划线空白标识符 _
来丢弃不需要的值。
_, err = io.Copy(dst, src) // 丢弃字节数
_, ok = x.(T) // 只检测类型,忽略具体值
类型
一个类型声明语句创建了一个新的类型名称,和现有类型具有相同的底层结构。新命名的类型提供了一个方法,用来分隔不同概念的类型,这样即使它们底层类型相同也是不兼容的。
type 类型名字 底层类型
类型声明语句一般出现在包一级,因此如果新创建的类型名字的首字符大写,则在包外部也可以使用。
包和文件
Go 语言中的包和其他语言的库或模块的概念类似,目的都是为了支持模块化、封装、单独编译和代码重用。
包的初始化
对于在包级别声明的变量,如果有初始化表达式则用表达式初始化,还有一些没有初始化表达式的,可以用一个特殊的 init
初始化函数来简化初始化工作。
func init() { /* ... */ }
这样的 init
初始化函数除了不能被调用或引用外,其他行为和普通函数类似。在每个文件中的 init
初始化函数,在程序开始执行时按照它们声明的顺序被自动调用。
每个包在解决依赖的前提下,以导入声明的顺序初始化,每个包只会被初始化一次。因此,如果一个 p
包导入了 q
包,那么在 p
包初始化的时候可以认为 q
包必然已经初始化过了。初始化工作是自下而上进行的,main
包最后被初始化。以这种方式,可以确保在 main
函数执行之前,所有依赖的包都已经完成初始化工作了。
作用域
一个声明语句将程序中的实体和一个名字关联,比如一个函数或一个变量。声明语句的作用域是指源代码中可以有效使用这个名字的范围。
作用域和生命周期区别
- 声明语句的作用域对应的是一个源代码的文本区域,它是一个编译时的属性。
- 一个变量的生命周期是指程序运行时变量存在的有效时间段,在此时间区域内它可以被程序的其他部分引用,是一个运行时的概念。