变量主要用来存储数据信息,变量的值可以通过变量名进行访问。Go语言的变量名的命名规则与其他语言一样,都是由字母、数字和下画线组成,其中变量名的首字符不能为数字。常见的变量的数据类型包括整型、浮点型、布尔型及结构体等。
变量的声明通常使用var关键字,变量的声明格式如下:var identifier type
var a int //声明整型类型的变量,保存整数数值
var b string //声明字符串类型的变量
var c []float32 //声明32位浮点切片类型的变量,浮点切片表示由多个浮点类型组成的数据结构
var d func() bool //声明返回值为布尔类型的函数变量
var e struct { //声明结构体类型的变量,该结构体拥有整型的x字段
x int
}
注意:Go语言和其他编程语言不同之处在于,它在声明变量时将变量的类型放在变量的名称之后。这样做的好处就是可以避免出现含糊不清的声明形式。例如,如果想要两个变量都是指针,不需要将它们分开书写,写成var a, b *int即可。
同样,可以一次声明多个变量。在声明多个变量时可以写成常量的那种形式,例如:
var (
a int
b string
c []float32
d func() bool
e struct {
x int
}
)
var a, b, c int
var a, b, c int = 1, 2, 3
a, b = 1, 2
a, b = b, a
Go语言在声明变量时,自动对变量对应的内存区域进行初始化操作。每个变量会初始化其类型的默认值,例如:
变量的初始化标准格式如下:var 变量名 类型 = 表达式
2和int同为int类型,因此可以进一步简化初始化的写法,即var a = 2
。
等号右边的部分在编译原理里被称为右值(rvalue)
var attack = 35
var defence = 15
var damageRate float32 = 0.28
var damage = float32(attack+defence) * damageRate
fmt.Println(damage)
var的变量声明还有一种更为精简的写法,即a = 2
该写法同样支持多个类型变量同时声明并赋值,例如:a, b := 1, 2
Go语言中,除了可以在全局声明中初始化实体,也可以在init函数中初始化。init函数是一个特殊的函数,它会在包完成初始化后自动执行,执行优先级比main函数高,并且不能手动调用init函数。每一个源文件有且只有一个init函数,初始化过程会根据包的依赖关系按顺序单线程执行。
可以在开始执行程序之前通过init函数来对数据进行检验与修复,保证程序执行时状态正常,例如:
package main
import (
"fmt"
"math"
)
// Pi 为圆周率
var Pi float64
func init() {
Pi = 4 * math.Atan(1) // 在init函数中计算Pi的值
}
func main() {
DPi := Pi * Pi
fmt.Println(Pi, DPi)
}
变量的交换是编程最简单的算法之一。在进行交换变量时,通常需要一个中间变量临时对变量进行保存。用传统方法编写变量交换代码如下:
var a int = 100
var b int = 200
var t int
t = a
a = b
b = t
fmt.Println(a, b)
传统方法的变量交换往往占用了较大的内存空间,因此,根据这一情况又发明了一些算法来避免使用中间变量,例如:
var a int = 100
var b int = 200
a = a ^ b
b = b ^ a
a = a ^ b
fmt.Println(a, b)
这种算法往往对数值范围和类型都有一定的要求。到了Go语言时,内存不再是紧缺资源,而且写法可以更加简单。使用Go语言的“多重赋值”特性,可以轻松完成变量交换的任务,例如:
var a int = 100
var b int = 200
a, b = b, a
fmt.Println(a, b)
在对多个变量同时赋值时,变量的左值和右值按从左到右的顺序依次赋值。多重赋值在Go语言的错误处理和函数返回值中会大量地使用。例如,使用Go语言进行排序时就需要使用变量的交换,代码如下:
type IntSlice []int
func (p IntSlice) Len() int {
return len(p)
}
func (p IntSlice) Less(i, j int) bool {
return p[i] < p[j]
}
func (p IntSlice) Swap(i, j int) {
p[i], p[j] = p[j], p[i]
}
在编码过程中,可能会遇到没有名称的变量、类型或方法。虽然这不是必需的,但有时候这样做可以极大地增强代码的灵活性,这些变量被统称为匿名变量。
匿名变量可以用下画线(“_”)表示,而“_”本身就是一个特殊的标识符,因此被称为空白标识符。它可以像其他标识符那样用于变量的声明或赋值(任何类型都可以赋值给它),但任何赋给这个标识符的值都将被抛弃,因此这些值不能在后续的代码中使用,也不可以使用这个标识符作为变量对其他变量进行赋值或运算。使用匿名变量时,只需要在变量声明的地方使用下画线替换即可。
func GetData() (int, int) {
return 100, 50
}
func main() {
a, _ := GetData()
_, b := GetData()
fmt.Println(a, b)
}
一个变量(常量、类型或函数)在程序中都有一定的作用范围,该作用范围被称为作用域。
在函数体内声明的变量称为局部变量,它们的作用域只在函数体内,函数的参数和返回值变量都属于局部变量。
局部变量不是一直存在的,它只在定义它的函数被调用后存在,函数调用结束后这个局部变量就会被销毁。
func main() {
//声明局部变量a 和 b 并赋值
var a int = 5
var b int = 3
//声明局部变量c 并计算 a 和 b 的和
c := a + b
fmt.Printf("a = %d, b = %d,c= %d\n", a, b, c)
}
在函数体外声明的变量称为全局变量,全局变量只需要在一个源文件中定义,就可以在所有源文件中使用。当然,不包含这个全局变量的源文件需要使用import关键字引入全局变量所在的源文件之后才能使用这个全局变量。
全局变量声明必须以var关键字开头,如果想要在外部包中使用,全局变量的首字母必须大写。
//声明全局变量
var c int
func main() {
//声明局部变量
var a, b int
//初始化参数
a = 5
b = 3
c = a + b
fmt.Printf("a = %d, b= %d, c = %d\n", a, b, c)
}
在定义函数时,函数名后面括号中的变量称为形式参数(简称形参)。形式参数只在函数调用时才会生效,函数调用结束后就会被销毁。在函数未被调用时,函数的形参并不占用实际的存储单元,也没有实际值。形式参数会作为函数的局部变量来使用。
func main() {
var a int = 10
var b int = 20
var c int = 0
fmt.Printf("main()函数中 a=%d\n", a)
c = sum(a, b)
fmt.Printf("main()函数中 c = %d\n", c)
}
/*函数定义-两数相加*/
func sum(a, b int) int {
fmt.Printf("sum() 函数中 a = %d\n", a)
fmt.Printf("sum() 函数中 b = %d\n", b)
return a + b
}