Go-知识简短变量声明
- 1. 简短变量声明符
- 2. 简短变量赋值可能会重新声明
- 3. 简短变量赋值不能用于函数外部
- 4. 简短变量赋值作用域问题
- 5. 总结
githuio地址:https://a18792721831.github.io/
1. 简短变量声明符
在Go语言中,可以使用关键字var
或直接使用简短变量声明符:=
声明变量。
相比而言,使用:=
更多一些,而且使用:=
可以自动推断类型,而不需要关注类型问题。
比如:
a := "string"
a := 2
a := struct{}
2. 简短变量赋值可能会重新声明
使用:=
可能会重新声明变量,导致出现在不同的作用域中,很可能创建了新的同名变量,导致同一个函数不同作用域的同名变量不符合预期。
多说无益,请看如下代码:
func TestTmpVar(t *testing.T) {
a := 1
a++
fmt.Printf("a=%d\n", a)
if a > 0 {
a, err := addNum(a)
if err != nil {
fmt.Printf("err=%s", err)
}
fmt.Printf("a=%d\n", a)
}
fmt.Printf("a=%d\n", a)
}
func addNum(a int) (int, error) {
return a + 1, nil
}
请想想上述代码输出结果是什么?
上面的写法非常常见,使用:=
调用了一个函数,然后接收函数返回的结果,如果有错误,那么处理错误,没有错误,那么将结果赋值给变量。
但是要非常注意,因为a
已经在外部声明了,而方法调用又是在if
内部,所以就相当于在if
内,创建了一个同名函数,并没有按照我们的预期处理。
如果a
是指针,那么,后面在使用a
的时候,肯定会出现空指针panic
。
为什么会出现这样的问题呢?
这是因为:=
的规则:
当
:=
左侧存在新变量时(err
),已声明的变量(a
)会被重新声明,不会有其他额外的副作用。
当:=
左侧没有新变量是不允许的,编译会提示no new variable on left side of :=
所以如果当一个变量第一次声明和后续全部使用过程中,都在同一个作用域内时,上述使用确不会出现问题,因为作用域相同。
比如上述代码如果去掉if
:
func TestTmpVar(t *testing.T) {
a := 1
a++
fmt.Printf("a=%d\n", a)
//if a > 0 {
a, err := addNum(a)
if err != nil {
fmt.Printf("err=%s", err)
}
fmt.Printf("a=%d\n", a)
//}
fmt.Printf("a=%d\n", a)
}
func addNum(a int) (int, error) {
return a + 1, nil
}
输出如下
因为虽然使用:=
重新定义了新的变量,但是在后面使用的过程中,使用的也是新的变量。
3. 简短变量赋值不能用于函数外部
简短变量赋值只能用于函数内,不能使用:=
来声明和初始化全局变量。
比如:
package study
test := "test"
会出现编译错误,提示为syntax error: non-declaration statement outside function body
。
可以理解为:=
实际上会拆分成两个语句,一个是声明,一个是赋值。而赋值语句不允许出现在函数外部。
4. 简短变量赋值作用域问题
考虑最开始的例子,假设变量时指针类型。
type tes struct {
a int
z string
}
func TestTmpStruct(t *testing.T) {
a := tes{
a: 1,
z: "1",
}
a.a++
fmt.Printf("a = %+v, %#p\n", a, &a)
if a.a > 0 {
a, err := addNumStruct(a)
if err != nil {
fmt.Println(err)
}
fmt.Printf("a = %+v, %#p\n", a, &a)
}
fmt.Printf("a = %+v, %#p\n", a, &a)
}
func addNumStruct(a tes) (tes, error) {
a.a++
return a, nil
}
查看输出,可以很明显的看到创建了新的变量:
那么新的问题来了,假设不是if
,而是for
那么:
可以很明显的看到创建了很多的变量,这些变量属于for
作用域内的临时变量,当大量生成临时变量时,
虽然Go不需要我们管理内存,但是会导致程序性能的下降。
5. 总结
简短变量声明操作符:=
虽然很好用,但是需要注意:=
的特性,在使用的时候,需要避免因为使用:=
而导致的同名变量声明,以及作用域内无效变量的声明。