文章

Go-知识简短变量声明

简短变量声明操作符:=虽然很好用,但是需要注意:=的特性,在使用的时候,需要避免因为使用:=而导致的同名变量声明,以及作用域内无效变量的声明。_go简短声明

Go-知识简短变量声明

文章信息

  • 原文链接:https://jiayq.blog.csdn.net/article/details/136428399
  • 发布时间:2024-03-03 11:16:24
  • 阅读量:1
  • 分类:Golang专栏收录该内容, 订阅专栏
  • 标签:#golang, #go, #简短变量声明, #Go操作符使用注意, #Go编程陷阱

摘要

文章浏览阅读1.5k次,点赞25次,收藏23次。简短变量声明操作符:=虽然很好用,但是需要注意:=的特性,在使用的时候,需要避免因为使用:=而导致的同名变量声明,以及作用域内无效变量的声明。_go简短声明


Go-知识简短变量声明

  • 1. 简短变量声明符
  • 2. 简短变量赋值可能会重新声明
  • 3. 简短变量赋值不能用于函数外部
  • 4. 简短变量赋值作用域问题
  • 5. 总结

githuio地址:https://a18792721831.github.io/

1. 简短变量声明符

在Go语言中,可以使用关键字var或直接使用简短变量声明符:=声明变量。
相比而言,使用:=更多一些,而且使用:=可以自动推断类型,而不需要关注类型问题。
比如:

1
2
3
    a := "string"
    a := 2
    a := struct{}

2. 简短变量赋值可能会重新声明

使用:=可能会重新声明变量,导致出现在不同的作用域中,很可能创建了新的同名变量,导致同一个函数不同作用域的同名变量不符合预期。
多说无益,请看如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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. 简短变量赋值不能用于函数外部

简短变量赋值只能用于函数内,不能使用:=来声明和初始化全局变量。
比如:

1
2
package study
test := "test"

会出现编译错误,提示为syntax error: non-declaration statement outside function body
可以理解为:=实际上会拆分成两个语句,一个是声明,一个是赋值。而赋值语句不允许出现在函数外部。

4. 简短变量赋值作用域问题

考虑最开始的例子,假设变量时指针类型。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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. 总结

简短变量声明操作符:=虽然很好用,但是需要注意:=的特性,在使用的时候,需要避免因为使用:=而导致的同名变量声明,以及作用域内无效变量的声明。

本文由作者按照 CC BY 4.0 进行授权