内容简介:片段一:片段二:可以看到,片段一和片段二中s1和s2输出不一致。
片段一:
s := []byte("") s1 := append(s,'a') s2 := append(s,'b') fmt.Println(s1,"=====",s2) // [97] ===== [98] fmt.Println(string(s1),"======",string(s2)) // a ====== b 复制代码
片段二:
s := []byte("") s1 := append(s,'a') s2 := append(s,'b') fmt.Println(string(s1),"======",string(s2)) // b ====== b 复制代码
可以看到,片段一和片段二中s1和s2输出不一致。
问题分析
初看起来,感觉是 fmt.Println(s1,"=====",s2)
这句话导致了结果的不一样。
具体原因,且看下面分解。
对于片段二,结果都是 b
,这个似乎是因为 append
的时候,赋值给了一个新的变量,导致了s指向的底层数据虽然改变了,但是s记录的len还是不变的,所以第二次append的时候,就把第一次的值给覆盖了。所以才得出了都是 b
的结果。
对于问题二的解释,其实还少考虑了一个问题,那就是如果在append的时候,底层数组重新分配了,那么,就不会出现这个问题了。不信,看下面这个例子:
s := []int{5, 7, 9} fmt.Printf("%d, %d, %p\n", len(s), cap(s), &s[0]) // 3, 3, 0xc000016240 x := append(s, 11) fmt.Printf("%d, %d, %p\n", len(x), cap(x), &x[0]) // 4, 6, 0xc0000141e0 y := append(s, 12) fmt.Printf("%d, %d, %p\n", len(y), cap(y), &y[0]) // 4, 6, 0xc000014210 fmt.Println(s, x, y) // [5 7 9] [5 7 9 11] [5 7 9 12] 复制代码
从上面例子可以看到,一开始s的len是3, cap也是3,在第一次append的时候,底层数组需要扩容,翻倍为6,所以x的len是4, cap是6,此时指向的底层数组地址已经不同了,第二个append同理。所以两次append,因为底层数据扩容的原因,两次append作用的地方是不同的,导致第二次没有覆盖第一次的数据。
通过上面的解释,我们知道了第一个片段出现的原因就是因为两次append都扩容了,所以没有出现覆盖的现象。而第二个片段没有出现扩容的情况,所以就出现了覆盖的情况。
那么为什么会这样呢,我们尝试打印一下,初始化s的cap,可以发现片段一中初始化s的cap为0,片段二为32。具体原因可以看下面的逃逸分析
逃逸分析
使用下面的命令进行分析。
go tool compile -m main.go 复制代码
片段一:
main.go:9:13: s1 escapes to heap main.go:6:13: ([]byte)("") escapes to heap main.go:9:17: "=====" escapes to heap main.go:9:17: s2 escapes to heap main.go:10:20: string(s1) escapes to heap main.go:10:20: string(s1) escapes to heap main.go:10:25: "======" escapes to heap main.go:10:40: string(s2) escapes to heap main.go:10:40: string(s2) escapes to heap main.go:9:13: main ... argument does not escape main.go:10:13: main ... argument does not escape 复制代码
可以看到 s1
和 s2
由于Println,逃逸到了heap上,所以s一开始的cap是0.
片段二:
main.go:9:20: string(s1) escapes to heap main.go:9:20: string(s1) escapes to heap main.go:9:25: "======" escapes to heap main.go:9:40: string(s2) escapes to heap main.go:9:40: string(s2) escapes to heap main.go:6:13: main ([]byte)("") does not escape main.go:9:13: main ... argument does not escape 复制代码
可以看到 s1
和 s2
没有逃逸,还是在栈上,所以s一开始的cap是32(默认).
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- Hive SQL 使用过程中的奇怪现象
- 需求与问题:一个老现象
- 深入探究 6 个 React 诡异现象
- 网络编程解决黏包现象
- CIO值得看看:DevOps现象 - ACM权威
- 程序员工资不会上涨的几个现象
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
数据化运营速成手册
胡晨川 / 电子工业出版社 / 2017-4 / 55
《数据化运营速成手册》用于提升互联网公司员工的数据应用能力,即数据化运营能力。首先,从最常用的数据图表切入,帮助执行层正确地绘图,管理层正确地看图;接着,梳理运营中最基本的数据应用知识,涉及数据获取、数据清洗、数据认知、分析框架、指标体系、运营实验等内容。然后,介绍作者认为必要的统计学知识,包括假设检验、方差分析、回归分析和时间序列分解,并引入了管理科学中的规划求解方法。最后,介绍了数据分析工具的......一起来看看 《数据化运营速成手册》 这本书的介绍吧!