【Golang 面试题】每日 3 题(十一)
✍个人博客:Pandaconda-CSDN博客
📣专栏地址:http://t.csdnimg.cn/UWz06
📚专栏简介:在这个专栏中,我将会分享 Golang 面试中常见的面试题给大家~
❤️如果有收获的话,欢迎点赞👍收藏📁,您的支持就是我创作的最大动力💪
31. Go 语言当中数组和切片的区别是什么?
在 Go 语言中,数组和切片都是用来存储一组相同类型的元素,但它们有一些不同之处,具体如下:
- 长度不同
数组的长度在定义时就确定了,不可更改,而切片的长度是可以动态增长和缩减的。
- 内存分配方式不同
数组是一个固定长度的数据结构,它在声明时就会分配一段连续的内存空间,而切片则是一个动态分配的数据结构,它的底层结构是一个指向数组的指针、长度和容量,容量可以随着元素的增加而自动增长。
- 传递方式不同
数组作为函数参数传递时,会被复制一份到函数栈中,因此在函数中修改数组的值并不会影响原数组;而切片作为函数参数传递时,会复制指向底层数组的指针、长度和容量,而不是整个底层数组,因此在函数中修改切片的值会影响原切片。
- 声明方式不同
数组的声明方式为:var array [n]T,其中 n 表示数组的长度,T 表示数组元素的类型。切片的声明方式为:var slice []T,其中 T 表示切片元素的类型。
综上所述,数组和切片都有自己的特点和优缺点,需要根据具体的需求来选择合适的数据结构。如果需要存储一组固定长度的元素,可以使用数组;如果需要动态增长和缩减元素,可以使用切片。
32. Go array 和 slice 的区别?
- 数组长度不同
- 数组初始化必须指定长度,并且长度就是固定的。
- 切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大。
- 函数传参不同
- 数组是值类型,将一个数组赋值给另一个数组时,传递的是一份深拷贝,函数传参操作都会复制整个数组数据,会占用额外的内存,函数内对数组元素值的修改,不会修改原数组内容。
- 切片是引用类型,将一个切片赋值给另一个切片时,传递的是一份浅拷贝,函数传参操作不会拷贝整个切片,只会复制 len 和 cap,底层共用同一个数组,不会占用额外的内存,函数内对数组元素值的修改,会修改原数组内容。
- 计算数组长度方式不同
- 数组需要遍历计算数组长度,时间复杂度为 O(n)。
- 切片底层包含 len 字段,可以通过 len() 计算切片长度,时间复杂度为 O(1)。
33. Golang Slice 的底层实现
在 Go 语言中,Slice 是一种基于数组的数据结构,它是一个拥有指向底层数组的指针、长度和容量属性的结构体。Slice 的底层实现是一个动态数组,也就是说,它可以动态地增长和缩小,同时具有数组的许多优点,例如可以进行索引和迭代操作等。
当创建一个 Slice 时,Go 语言会在内存中分配一块连续的内存空间用于存储数据,并返回一个指向该内存区域的指针。该指针称为 Slice 的底层指针。Slice 还会记录该内存区域的长度和容量。
在 Slice 容量不足以存储新的元素时,Go 语言会自动重新分配一块更大的内存区域,并将原有的元素复制到新的内存区域中,然后将新的元素添加到新的内存区域中。这种自动扩容机制使得 Slice 的大小可以根据需要自动调整,无需手动进行内存分配和释放操作,同时也保证了 Slice 的连续性,使得它在访问和遍历元素时具有更好的性能表现。
需要注意的是,由于 Slice 是对底层数组的引用,因此多个 Slice 可以共享同一个底层数组。这种特性使得 Slice 在函数之间传递时非常高效,同时也需要注意避免对 Slice 中的元素进行修改,从而影响到其他共享同一个底层数组的 Slice。