Go中的数组属于值类型,通常应该存储于栈中,局部变量依然会根据逃逸分析确定存储栈还是堆中 。
编译器对数组函数中做两种不同的优化:
在静态区完成赋值后复制到栈中 。
总结起来,在不考虑逃逸分析的情况下,如果数组中元素的个数小于或者等于 4 个 , 那么所有的变量会直接在栈上初始化,如果数组元素大于 4 个,变量就会在静态存储区初始化然后拷贝到栈上 。
由于数组是值类型,那么赋值和函数传参操作都会复制整个数组数据 。
不管是赋值或函数传参,地址都不一致,发生了拷贝 。如果数组的数据较大,则会消耗掉大量内存 。那么为了减少拷贝我们可以主动的传递指针呀 。
地址是一样的,不过传指针会有一个弊端 , 从打印结果可以看到,指针地址都是同一个,万一原数组的指针指向更改了,那么函数里面的指针指向都会跟着更改 。
同样的我们将数组转换为切片,通过传递切片,地址是不一样的 , 数组值相同 。
切片是引用传递,所以它们不需要使用额外的内存并且比使用数组更有效率 。
所以,切片属于引用类型 。
通过这种方式可以将数组转换为切片 。
中间不加三个点就是切片,使用这种方式创建切片,实际上是先创建数组 , 然后再通过第一种方式创建 。
使用make创建切片,就不光编译期了,make创建切片会涉及到运行期 。1. 切片的大小和容量是否足够?。?
切片是否发生了逃逸 , 最终在堆上初始化 。如果切片小的话会先在栈或静态区进行创建 。
切片有一个数组的指针 , len是指切片的长度, cap指的是切片的容量 。
cap是在初始化切片是生成的容量 。
发现切片的结构体是数组的地址指针array unsafe.Pointer,而Go中数组的地址代表数组结构体的地址 。
slice 中得到一块内存地址,array[0]或者unsafe.Pointer(array[0]) 。
也可以通过地址构造切片
nil切片:指的unsafe.Pointer 为nil
空切片:
创建的指针不为空,len和cap为空
当一个切片的容量满了,就需要扩容了 。怎么扩,策略是什么?
如果原来数组切片的容量已经达到了最大值,再想扩容,Go 默认会先开一片内存区域,把原来的值拷贝过来,然后再执行 append() 操作 。这种情况对现数组的地址和原数组地址不相同 。
从上面结果我们可以看到,如果用 range 的方式去遍历一个切片,拿到的 Value 其实是切片里面的值拷贝,即浅拷贝 。所以每次打印 Value 的地址都不变 。
由于 Value 是值拷贝的,并非引用传递,所以直接改 Value 是达不到更改原切片值的目的的,需要通过 slice[index] 获取真实的地址 。
go语言中数组使用的注意事项和细节1、数组是多个 相同类型 的数据的组合,一个数组一旦声明/定义了,其 长度是固定的,不能动态变化。
2、var arr []int这时arr就是一个slice 切片。
3、数组中的元素可以是任何数据类型 , 包括值类型和引用类型 , 但是 不能混用。
4、数组创建后 , 如果没有赋值,有默认值如下:
数值类型数组:默认值为 0
字符串数组:默认值为 ""
bool数组:默认值为 false
5、使用数组的步骤:
(1)声明数组并开辟空间
(3)给数组各个元素赋值
(3)使用数组
6、数组的下标是从0开始的 。
7、数组下标必须在指定范围内使用,否则报panic:数组越界,比如var arr [5]int的有效下标为0~4.
8、Go的数组属于 值类型 , 在默认情况下是 值传递 ,因此会进行值拷贝 。数组间不会相互影响 。
推荐阅读
- 直播伴侣文字直播,直播伴侣怎么打字
- jquery事件一直调用,jquery事件处理程序返回false
- postgre角色权限的简单介绍
- erp系统怎么做合同模板,erp合同管理系统
- 素数之和c语言函数 求素数的c语言程序函数
- 安卓手机微信提醒功能,安卓微信的提示音是什么
- 十大休闲游戏,十大休闲游戏推荐
- phpcms自定义限制,phpcms怎么用
- vb.net哪个版本好用 vbnet ide