变量声明
变量是某个值的存储位置,而变量声明则创建了变量并将一个标识符(变量名)绑定到这个变量。
让我们先来看一段程序:
package main
import (
format "fmt" // 给fmt包设置别名为format
)
/*将0到100摄氏度每隔10度转换成华氏度并打印出来
C=5/9*(F-32)
*/
func main() {
var c,f int //c和f是整型,默认初始化为0
var lower, upper = 0, 100 // lower和upper分别初始化为0和100,都推导为整型
var step int = 10 // step是整型,初始化为10
for c = lower; c <= upper; c+=step {
f = c*9/5+32
format.Println(c,"\t",f)
}
}
Go语言中变量需要先声明再使用。变量声明的语法如下:
var 变量名列表 类型名 = 初始值列表
- 变量名列表中的变量以逗号分割,初始值列表中的初始值以逗号分割。如果在变量声明中指定了初始值列表,则初始值的个数必须与变量名列表中的变量个数相同。
- 在同一层级的块内,变量不能被重新声明。关于块的详细概念,我们将在后面讲解,这里暂时简单理解为一对匹配的花括号,块是可以嵌套的,所以存在层级关系。
在变量声明中如果指定了类型名,则变量名列表中所有的变量都是所指定的类型,此时初始值列表可以省略,如果省略了初始值列表,变量会被初始化为各自类型的“零值”(关于类型的“零值”,将在数据类型一章中讲解)。本章开头的例子中c,f被初始化为int型零值0,step被初始化为10:
var c,f int
var step int = 10
在变量声明中如果没有指定类型名,初始值列表不能省略,变量名列表中的各变量类型分别由初始值列表类型推导而来(关于类型推导,也将留在后面讲解)。在本章开头的例子中变量lower和upper的类型分别由0和100推导得到,均为int型:
var lower, upper = 0, 100
短式变量声明
在函数体的内部(只能在函数体内部)还可以使用短式变量声明,语法如下:
变量名列表 :=初始值列表
变量名列表中的各变量类型分别由初始值列表类型推导而来;初始值列表数量必须与变量名列表数量一致。
它相当相于常规变量声明:
var 变量名列表 = 初始值列表
在同一层级块中,如果已经声明过的变量与至少一个新变量一同出现在短式变量声明的变量列表中,则被声明过的变量以可被重新声明,但不能改变类型(其实质是对旧变量赋新值):
var i int =0
i,j := 1,1.0 // i的新值为1,也是整型,声明了新变量j,值为1.0是个浮点型
i,k := 1.0,1 // 编译错误,1.0是浮点型,i的类型是整型,不能重新声明为浮点型
常量声明
在程序中不希望被改变的值可以声明为常量,常量声明的语法我们通过下以的示例来学习:
const a, b int = 0, 1 //a和b是int型常量,值分别为0和1
const c, d = "test", "string" //c和d是字符串型常量,值分别是test和string
const (
q, r = 1, 1 //q和r是整型常量,值分别是1和1
s, t //s和t不指定类型,则以上一行为模板,是整型常量,值分别是1和1
w, x = "test2", "string2" //w和x是字符串常量,值是test2和string2
e // 错误,列表个数不同,不能以上一行为模板,应该要赋值
)
上面的示例展示了常量的声明方法,同时也展示了go语言预定义常量标识符iota的使用方法。
iota常量
iota 是个预定义的无类型整数常量,表示的是常量声明的当前索引值:
const A = iota // iota = 0
const B = iota // iota = 0
const (
C = -1 // iota=0,无用
D = iota // iota=1,所以D值为1
E, F, G = iota,iota, 6.1 // iota=2,所以E和F都是整型,值都为2;G为浮点型,值为6.1
H, I, J // iota=3,H、I和J不指定类型,则以上一行为模板,H和I值为iota,即都为3;J为浮点值为6.1
K, L, M int // 错误,指定了类型,需要指定值
)
函数声明
在之前的例子中我们已经接触过main函数。函数的作用就是完成某个特定的功能,main函数提供了我们所编写的程序的入口功能。
Go语言函数允许多个返回值,函数声明的基本语法:
func 函数名 (参数表) (返回值表) {
函数体
}
参数表与返回值表一起,构成函数签名。
参数表中的参数要么都有名字,要么都没有。同样的,返回值表中的返回值要么都有名字,要么都没有。例如:
// 函数名subStr,接受string型参数s以及int型参数offset和length,返回值是string型和error型
func subStr(s string, offset, length int, ) (string, error) {
return s, nil
}
如果返回值只有一个且返回值没有名字,则返回值列表的括号可以省略:
func fun1(s string) int
参数和返回值如果都有名字,它们的名字不能重复。例如下面的例子是错误的:
// 错误的例子,参数名和返回值名重复了
func fun2(s string) (s error)
给返回值命名的意义在于,可以使用无参数的返回语句,例如:
// 返回时不需要再为return语句指定参数
func SliceInfo(s []string) (length, capacity int) {
length = len(s)
capacity= cap(s)
return
}
// 返回值 i和j的零值是0,所以函数的返回值是0,0
func fun3(s string) (i,j int){
return
}
如果一个函数有返回值,则函数的所有执行路径的最后必须要有终止语句。
终止语句
- return或goto
- panic调用
- 在一个块的结尾遇到了终止语句
- 没有循环条件且break不会打断for循环的for语句
- 标识了终止语句的标签语句
关于panic、for语句和标签语句会在后续讲解。