- GO语言学习资料推荐:Go语言圣经 《The Go Programming Language》中文翻译版 :http://books.studygolang.com/gopl-zh/
命名
名字必须以一个字母或下划线开头,后面可跟数字、字母、下划线。区分大小写
关键字:
1 | break default func interface select |
**预定义名字:**主要对应内建常量、类型和函数
1 | 内建常量: true false iota nil |
声明
Go语言主要有四种类型的声明语句:var、const、type 和 func,分别对应变量、常量、类型和函数实体对象的声明。
1 | //声明包 |
变量
var声明语句可以创建一个特定类型的变量,然后给变量附加一个名字,并且设置变量的初始值。变量声明的一般语法如下:
1 | var 变量名字 类型 = 表达式 |
其中 “类型 “ 或 “= 表达式” 两个部分可以省略其中的一个。如果省略的是类型信息,那么将根据初始化表达式来推导变量的类型信息。如果初始化表达式被省略,那么将用零值初始化该变量。
**零值初始化机制:**可以确保每个声明的变量总是有一个良好定义的值,因此在Go语言中不存在未初始化的变量。
数值类型变量对应的零值:0
布尔类型变量对应的零值:false
字符串类型对应的零值:”“
接口或引用类型(包括slice、指针、map、chan和函数)变量对应的零值:nil
数组或结构体等聚合类型对应的零值:每个元素或字段都是对应该类型的零值。
多变量声明
可同时声明多个变量,如果省略每个变量的类型,将可以声明多个类型不同的变量(类型由初始化表达式推导):
1 | var i, j, k int // int, int, int |
一组变量也可以通过调用一个函数,由函数返回的多个返回值初始化:
1 | var f, err = os.Open(name) // os.Open returns a file and an error |
简短变量声明
1 | 变量名 := 表达式 |
1 | anim := gif.GIF{LoopCount: nframes} |
和var形式声明语句一样,简短变量声明语句也可以用来声明和初始化一组变量:
1 | i, j := 0, 1 |
注意区分: **” := “**是变量声明语句, **”=“**是变量赋值操作
将右边各个表达式的值赋值给左边对应位置的各个变量:
1 | i, j = j, i // 交换 i 和 j 的值 |
但如果变量之前声明过,则再次使用:=声明则是赋值行为,其中err变量之前已经声明,则后面是对其进行赋值。且简短变量声明必须有一个新的变量被声明,否则编译不通过。
1 | in, err := os.Open(infile) |
指针
一个变量对应一个保存了变量对应类型值的内存空间。
一个指针的值是另一个变量的地址。
一个指针对应变量在内存中的存储位置。
并不是每一个值都会有一个内存地址,但是对于每一个变量必然有对应的内存地址。
通过指针,我们可以直接读或更新对应变量的值,而不需要知道该变量的名字(如果变量有名字的话)。
如果用“var x int”声明语句声明一个x变量,那么&x表达式(取x变量的内存地址)将产生一个指向该整数变量的指针,指针对应的数据类型是*int,指针被称之为“指向int类型的指针”。如果指针名字为p,那么可以说“p指针指向变量x”,或者说“p指针保存了x变量的内存地址”。同时*p表达式对应p指针指向的变量的值。一般*p表达式读取指针指向的变量的值,这里为int类型的值,同时因为*p对应一个变量,所以该表达式也可以出现在赋值语句的左边,表示更新指针所指向的变量的值。
1 | //声明变量 |
任何类型的指针的零值都是nil。如果p指向某个有效变量,那么p != nil测试为真。指针之间也是可以进行相等测试的,只有当它们指向同一个变量或全部是nil时才相等。
1 | var x, y int |
new函数
创建变量还可以通过调用内建的new函数。表达式new(T)将创建一个T类型的匿名变量,初始化为T类型的零值,然后返回变量地址,返回的指针类型为*T。
1 | p := new(int) // p, *int 类型, 指向匿名的 int 变量 |
由于new只是一个预定义的函数,它并不是一个关键字,因此我们可以将new名字重新定义为别的类型。例如下面的例子:
1 | func delta(old, new int) int { return new - old } |
由于new被定义为int类型的变量名,因此在delta函数内部是无法使用内置的new函数的。
变量的声明周期
变量的生命周期指的是在程序运行期间变量有效存在的时间段。对于在包一级声明的变量来说,它们的生命周期和整个程序的运行周期是一致的。而相比之下,局部变量的生命周期则是动态的:每次从创建一个新变量的声明语句开始,直到该变量不再被引用为止,然后变量的存储空间可能被回收。函数的参数变量和返回值变量都是局部变量。它们在函数每次被调用的时候创建。
赋值
1 | x = 1 // 命名变量的赋值 |
特定的二元算术运算符和赋值语句的复合操作有一个简洁形式,例如上面最后的语句可以重写为:
1 | count[x] *= scale |
数值变量也可以支持++递增和--递减语句(译注:自增和自减是语句,而不是表达式,因此x = i++之类的表达式是错误的):
1 | v := 1 |