「这是我参与11月更文挑战的第25天,活动详情查看:2021最后一次更文挑战」。
Go语言学习查缺补漏ing Day7
本文收录于我的专栏:《让我们一起Golang》
一、再谈defer的执行顺序
大家来看一看这段代码:
1 | go复制代码package main |
前面我们介绍过defer的执行顺序,但是我今天又遇到新问题,于是这里又补充介绍这个defer的顺序问题。
这个程序运行结果是:
1 | 复制代码21 |
我们都知道defer的执行顺序是先进后出,所以执行顺序是C、B、A。
B中defer fmt.Println(person.age)
输出28,为什么呢?
因为这里是将28作为defer()函数的参数,会把28推入栈中进行缓存,得到执行这条defer语句时就把它拿出来。所以输出28.
而A中:
1 | go复制代码defer func(p *Person) { |
defer()函数是将结构体Person的地址进行缓存,当后续改变这个地址的内值时,后续输出时这里就会输出那个地址内改变后的值。所以B defer语句执行时从地址中取出的值是29.
而C defer语句理由很简单:
1 | go复制代码defer func() { |
就是无参匿名函数的一种情形。闭包引用,person.age改变就会改变。
二、哪种切片的声明比较好?为什么?
1 | css复制代码var a []int |
这里第一种声明的是nil切片,而第二种声明是创建一个长度以及容量为零的空切片。
第一种切片声明方法比较好,因为它这种声明方式不占用空间,而第二种声明后会占用一部分空间。
三、取得结构体成员的几种方法
1 | go复制代码package main |
我们运行能够发现:
p、p2都能获取结构体的成员变量。
为什么呢?f()函数的返回值是指针类型,所以p2获取*f()时,p2是S类型,p2.m可以获取其成员变量。
而f()的结果是指针,不过我们前面说过,一级指针能够自动进行解引用。所以也能够访问成员变量。
四、遍历map的存在顺序变化?为什么?
我们执行下面这段代码多次,看输出结果:
1 | go复制代码package main |
第一次执行结果如下:
1 | sql复制代码5 five |
第二次执行结果如下:
1 | sql复制代码0 zero |
第三次执行结果如下:
1 | sql复制代码4 four |
我们发现每一次执行的顺序都是变化的。这说明遍历map的顺序是无序的。为什么呢?
在runtime.mapiterinit中有这样一段代码:
1 | go复制代码// mapiterinit initializes the hiter struct used for ranging over maps. |
1 | go复制代码 // decide where to start |
我们可以看到,决定从哪开始是根据fastrand()取随机数决定的,所以每次运行,随机数都不一样,所以输出顺序也不一样。
本文转载自: 掘金