Go 语言变量的声明
Go 语言是静态类型语言,因此变量 (variable) 是有明确类型的,编译器也会检查变量类型的正确性。
Go 语言的基本类型:
- bool
- string
- int、int8、int16、int32、int64
- uint、uint8、uint16、uint32、uint64、uintptr
- byte // uint8 的别名
- rune // int32 的别名,代表一个 Unicode 码
- float32、float64
- complex64、complex128
当一个变量被声明之后,系统会自动赋予它该类型的零值:int 为 0,float 为 0.0,bool 为 false,string 为空字符串,切片、函数、指针变量为 nil 等。所有的内存在 Go 中都是经过初始化的。
标准格式
变量声明以关键字 var
开头,后置变量类型,行尾无需分号。
var 变量名 变量类型
批量格式
- 相同类型的变量声明
// 只声明变量,不赋值(系统会自动赋予该类型的零值)
var a, b, c int
// 声明变量并赋值, 按顺序一一对应
var d, e, f int = 10, 20, 30
- 不同类型的变量声明
使用关键字 var
和括号,可以将一组变量定义放在一块。
var (
a int
b string
c []float32
d func() bool
e struct {
x int
}
)
简短格式(自动推导类型)
除 var
关键字外,还可使用更简短的变量定义和初始化语法。这是 Go 语言的推导声明写法,编译器会自动根据右值类型推断出左值的对应类型
变量名 := 表达式
需要注意的是,简短格式 (short variable declaration) 有以下限制:
- 定义变量,同时显示初始化
- 不能提供数据类型
- 只能用在函数内部
简短格式变量声明一组变量:
i, j := 0, 1
func main() {
x := 100
a, s := 1, "abc"
}
简短变量声明多用于局部变量的声明和初始化。var 形式的声明语句往往用于需要显示指定变量类型的地方,或着因为变量稍后会被重新赋值而初始值无关紧要的地方。
编译器推导类型的格式
在标准格式的基础上,将类型省略后,编译器会尝试根据等号右边的表达式推导变量的类型。等号右边的比分在编译原理里被称作右值(rvalue)。
var 变量名 = 表达式
Go 语言的多重赋值
以往我们进行变量交换的时候,传统的方式是需要一个中间变量进行变量的临时保存。又或者为了不占用内存,使用其他的一些算法来避免使中间变量,这样的算法很多,但是都有一定的数值范围和类型要求。
var a int = 100
var b int =200
a = a * b
b = a / b
a = a / b
fmt.Println(a, b) // 200 100
在 Go 语言中,使用 Go 的 "多重赋值" 特性,可以轻松完成变量交换的任务:
var a int = 100
var b int = 200
b, a = a, b
fmt.Println(a, b) // 200 100
多重赋值时,变量的左值和右值按从左到右的顺序赋值。
Go 语言的匿名变量
匿名变量不占用内存空间,不会分配内存。
匿名变量与匿名变量之间也不会因为多次声明而无法使用。
匿名变量的特点是一个下画线 "", "" 本身就是一个特殊的标识符,被称为空白标识符。它可以像其他标识符那样用于变量的声明或赋值(任何类型都可以赋值给它),但任何赋给这个标识符的值都会被抛弃,因为这些值不能在后续的代码中使用,也不可以使用这个标识符作为变量对其他变量进行赋值或运算。使用匿名变量时,只需要在变量声明的地方使用下画线替换即可。
func GetData() (int, int) {
return 100, 200
}
func main() {
a, _ = GetData() // 只取第一个值
_, b = GetData() // 只取第二个值
fmt.Println(a, b) // 100 200
}
Go 语言变量的作用域(与 js 类似)
作用域:一个变量(常量、类型或函数)在程序中的作用范围。
根据变量定义位置的不同,可以分为以下三个类型:
- 函数内定义的变量成为局部变量
- 函数外定义的变量称为全局变量
- 函数定义中的变量成为形式参数
局部变量
在函数体内声明的变量称之为局部变量,它们的作用域只在函数体内,函数的参数和返回值变量都属于局部变量。
函数变量不是一直存在的,它只在定义它的函数被调用后存在,函数调用结束后这个局部变量会被销毁。
全局变量
在函数体外声明的变量称之为全局变量,全局变量只需要在一个源文件中定义,就可以在所有源文件中使用,当然,不包含这个全局变量的源文件需要使用 "import" 关键字引入全局变量所在的源文件之后才能使用这个全局变量。
全局变量声明必须以 var 关键字开头,如果想要在外部包中使用全局变量的首字母必须大写。
Go 语言程序中全局变量与局部变量名称也可以相同,但是函数体内的局部变量会被优先考虑(类似于 js 的作用域链)。
形式参数
在定义函数时函数名后面括号中的变量叫做形式参数(简称形参)。形参只在函数调用时才会生效,函数调用结束后就会被销毁,在函数未被调用时,函数的形参并不占用实际的存储单元,也没有实际值。
形参会作为函数的局部变量来使用。
package main
import "fmt"
// 全局变量 a
var a int = 13
func main() {
fmt.Printf("全局变量 a = %d\n", a)
// 声明局部变量 a 和 b 并赋值
var a, b int = 3, 4
fmt.Printf("main() 函数中 a = %d\n", a)
fmt.Printf("main() 函数中 b = %d\n", b)
// 声明局部变量 c 并计算 a 和 b 的和
c := sum(a, b)
fmt.Printf("main() 函数中 c = %d\n", c)
}
// a 和 b 为形参
func sum(a, b int) int {
fmt.Printf("sum() 函数中 a = %d\n", a)
fmt.Printf("sum() 函数中 b = %d\n", b)
num := a + b
return num
}
Go 语言整型(整数类型)
Go 语言的数值类型分为以下几种:整数、浮点数、复数,其中每一种都包含了不同大小的数值类型,例如有符号整数包含 int8、int16、int32、int64 等,每种数值类型都决定了对应的大小范围和是否支持正负符号。
Go 语言同时提供了有符号和无符号的整数,类型其中包括 int8、int16、int32、int64 四种大小截然不同的有符号整数类型,分别对应8、16、32、64 bit(二进制位) 大小的有符号整数,于此对应的是 uint8、uint16、uint32、uint64 四种无符号整数类型。
此外还有两种整数类型 int 和 uint,它们分别对应特定 CPU 平台得字长(机器字大小),其中 int 表示有符号整数,应用最为广泛,uint 表示无符号整数。实际开发中由于编译器和计算机硬件的不同,int 和 uint 所能表示的整数大小会在 32bit 或 64bit 之间变化。
大多数情况下,我们只需要 int 一种整型即可,它可以用于循环计数器(for 循环中控制循环此的变量)、数组和切片的索引,以及任何通用目的的整型运算符,通常 int 类型的处理速度也是最快的。
Go 语言中有符号整数采用 2 的补码形式表示,也就是最高 bit 位用来表示符号位,一个 n-bit 的有符号数的取值范围是从 -2^(n-1)
到 2^(n-1) - 1
。无符号整数的所有 bit 位都用于表示非负数,取值范围是 0
到 2^n - 1
。例如,int8 类型整数的取值范围是从 -128
到 127
,而 uint8 类型整数的取值范围是从 0
到 255
。
Go 语言的浮点类型(小数类型)
Go 语言提供了两种精度的浮点数 float32
和 float64
。一个 float32
类型的浮点数可以提供大约 6 个十进制数的精度,而 float64 则可以提供约 15 个十进制数的精度,通常应优先使用 float64 类型,因为 float32 类型的累计计算误差很容易扩散,并且 float32 能精确表示的正整数并不是很大。
浮点数取值范围的极限值可以在 math
包中找到:
- 常量
math.MaxFloat32
表示float32
能取到的最大数值,大约是3.4e38
- 常量
math.MaxFloat64
表示float64
能取到的最大数值,大约是1.8e308
-
float32
和float64
能表示的最小值分别为1.4e-45
和4.9e-324
Go 语言的复数
在计算机中,复数是由两个浮点数表示的,其中一个表示实部(real),一个表示虚部(imag)。
Go 语言中的复数的类型有两种,分别是 complex128
(64位实数和虚数)和 complex64
(32位实数和虚数),其中 complex128 为复数的默认类型。
复数的值由三部分组成 RE + IMi
, 其中 RE 是实数部分,IM是虚数部分,RE 和 IM 均为 float 类型,而最后的 i 是虚数单位。
声明复数的语法格式:
var name complex128 = complex(x. y)
x, y 分别表示构成该复数的两个 float64 类型的数值,x 为实部,y 为虚部。
也可用简短格式:
name := complex(x, y)
可以通过 Go 语言的内置函数 real(z)
来获取该复数的实部,也就是 x;通过 imag(z)
获得该复数的虚部,也就是 y。
复数运算法则
复数也可以用 ==
和 !=
进行相等比较,只有两个复数的实部和虚部都相等的是哦胡它们才是相等的。