任何一门语言里面最基础的莫过于变量了。如果把内存比喻成一格一格整齐排列的储物箱,那么变量就是每个储物箱的标识,我们通过变量来访问计算机内存。没有变量的程序对于人类来说是可怕的,需要我们用数字位置来定位内存的格子,人类极不擅长这样的事。这就好比一岁半左右的幼儿还没有学会很多名词,只能用手来对物体指指点点来表达自己的喜好。变量让程序逻辑有了丰富的表达形式。
定义变量的三种方式
Go 语言的变量定义有多种形式,我们先看最繁琐的形式
package main
import "fmt"
func main() {
var s int = 42
fmt.Println(s)
}
-------------
42
package main
import "fmt"
func main() {
var s = 42
fmt.Println(s)
}
---------------
42
package main
import "fmt"
func main() {
s := 42
fmt.Println(s)
}
---------------
42
这三种变量定义方式都是可行的,各有其优缺点。可读性最强的是第一种,写起来最方便的是第三种,第二种是介于两者之间的形式。
类型是变量身份的象征,如果一个变量不那么在乎自己的身份,那在形式上就可以随意一些。var 的意思就是告诉读者「我很重要,你要注意」,:= 的意思是告诉读者「我很随意,别把我当回事」。var 再带上显式的类型信息是为了方便读者快速识别变量的身份。
如果一个变量很重要,建议使用第一种显式声明类型的方式来定义,比如全局变量的定义就比较偏好第一种定义方式。如果要使用一个不那么重要的局部变量,就可以使用第三种。比如循环下标变量
for i:=0; i<10; i++ {
doSomething()
}
var i = 0
for ; i<10; i++ {
doSomething()
}
package main
import "fmt"
func main() {
var i int
fmt.Println(i)
}
-----------
0
全局变量和局部变量
上面我们在代码例子中编写的变量都是局部变量,它定义在函数内部,函数调用结束它就消亡了。与之对应的是全局变量,在程序运行期间,它一直存在,它定义在函数外面。
package main
import "fmt"
var globali int = 24
func main() {
var locali int = 42
fmt.Println(globali, locali)
}
---------------
24 42
学过 C 语言的同学可能会问,Go 语言里有没有静态变量呢?答案是没有。
变量与常量
Go 语言还提供了常量关键字 const,用于定义常量。常量可以是全局常量也可以是局部常量。你不可以修改常量,否则编译器会抱怨。常量必须初始化,因为它无法二次赋值。全局常量的大小写规则和变量是一致的。
package main
import "fmt"
const globali int = 24
func main() {
const locali int = 42
fmt.Println(globali, locali)
}
指针类型
Go 语言被称为互联网时代的 C 语言,它延续使用了 C 语言的指针类型。
package main
import "fmt"
func main() {
var value int = 42
var pointer *int = &value
fmt.Println(pointer, *pointer)
}
--------------
0xc4200160a0 42
package main
import "fmt"
func main() {
var value int = 42
var p1 *int = &value
var p2 **int = &p1
var p3 ***int = &p2
fmt.Println(p1, p2, p3)
fmt.Println(*p1, **p2, ***p3)
}
----------
0xc4200160a0 0xc42000c028 0xc42000c030
42 42 42

如果普通的变量是一个储物箱,那么指针变量就是另一个储物箱,这个储物箱里存放了普通变量所在储物箱的钥匙。通过多级指针来读取变量值就好比在玩一个解密游戏。
Go 语言基础类型大全
Go 语言定义了非常丰富的基础类型,下面我列举了所有的基础数据类型。
package main
import "fmt"
func main() {
// 有符号整数,可以表示正负
var a int8 = 1 // 1 字节
var b int16 = 2 // 2 字节
var c int32 = 3 // 4 字节
var d int64 = 4 // 8 字节
fmt.Println(a, b, c, d)
// 无符号整数,只能表示非负数
var ua uint8 = 1
var ub uint16 = 2
var uc uint32 = 3
var ud uint64 = 4
fmt.Println(ua, ub, uc, ud)
// int 类型,在32位机器上占4个字节,在64位机器上占8个字节
var e int = 5
var ue uint = 5
fmt.Println(e, ue)
// bool 类型
var f bool = true
fmt.Println(f)
// 字节类型
var j byte = 'a'
fmt.Println(j)
// 字符串类型
var g string = "abcdefg"
fmt.Println(g)
// 浮点数
var h float32 = 3.14
var i float64 = 3.141592653
fmt.Println(h, i)
}
-------------
1 2 3 4
1 2 3 4
5 5
true
abcdefg
3.14 3.141592653
97
复数类型 complex64 和 complex128
unicode字符类型 rune
uintptr 指针类型
下一节我们开讲 Go 语言的条件判断与循环语句

阅读更多精彩文章,扫一扫关注公众号「码洞」