1. 变量声明
要单纯声明一个变量,可以通过 var
关键字,如下所示:
var s string
该示例只是声明了一个变量 s
,类型为 string
,并没有对它进行初始化,所以它的值为 string
的零值,也就是 “”(空字符串)。
来声明一个指针类型的变量试试,如下所示:
var sp *string
发现也是可以的,但是它同样没有被初始化,所以它的值是 *string
类型的零值,也就是 nil
。
2. 变量初始化
变量可以通过 =
运算符赋值,也就是修改变量的值。如果在声明一个变量的时候就给这个变量赋值,这种操作就称为变量的初始化。
如果要对一个变量初始化,可以有三种办法。
- 声明时直接初始化
var s string = "hello"
- 声明后再进行初始化
var s string
s = "hello"
- 使用
:=
简单声明
s := "hello"
3. 不同类型变量赋值
3.1 值类型变量
func main() {
var s string
s = "hello"
fmt.Println(s)
}
运行以上代码,可以正常打印,说明值类型的变量没有初始化时,直接赋值是没有问题的。
3.2 指针类型的变量呢
func main() {
var sp *string
*sp = "hello"
fmt.Println(*sp)
}
运行这些代码,你会看到如下错误信息:
panic: runtime error: invalid memory address or nil pointer dereference
这是因为指针类型的变量如果没有分配内存,就默认是零值 nil
,它没有指向的内存,所以无法使用,强行使用就会得到以上 nil
指针错误。
而对于值类型来说,即使只声明一个变量,没有对其初始化,该变量也会有分配好的内存。
在下面的示例中,声明了一个变量 s
,并没有对其初始化,但是可以通过 &s
获取它的内存地址。这其实是 Go
语言帮我们做的,可以直接使用。
func main() {
var s string
fmt.Printf("%p\n",&s)
}
为什么 var wg sync.WaitGroup
声明的变量 wg
不进行初始化也可以直接使用?
因为 sync.WaitGroup
是一个 struct
结构体,是一个值类型,Go
语言自动分配了内存,所以可以直接使用,不会报 nil
异常。
总结: 如果要对一个变量赋值,这个变量必须有对应的分配好的内存,这样才可以对这块内存操作,完成赋值的目的。
注意:其实不止赋值操作,对于指针变量,如果没有分配内存,取值操作一样会报
nil
异常,因为没有可以操作的内存。
所以一个变量必须要经过声明、内存分配才能赋值,才可以在声明的时候进行初始化。指针类型在声明的时候,Go
语言并没有自动分配内存,所以不能对其进行赋值操作,这和值类型不一样。
所以 map
和 chan
也一样,因为它们本质上也是指针类型。
func main() {
var d map[string]string
d["aa"] = "123"
fmt.Printf("%v\n", d)
}
报错:
panic: assignment to entry in nil map