golang中数组与切片的区别详析
作者:周?-_- 发布时间:2024-04-25 15:08:46
一. Go 切片和 Go 数组定义
Go 切片:又称动态数组,它实际是基于数组类型做的一层封装。
Go 数组:数组是内置(build-in)类型,是一组同类型数据的集合,它是值类型,通过从 0 开始的下标索引访问元素值。在初始化后长度是固定的,无法修改其长度。当作为方法的参数传入时将复制一份数组而不是引用同一指针。数组的长度也是其类型的一部分,通过内置函数 len(array)获取其长度。
二.切片与数组的区别
Go 数组与像 C/C++等语言中数组略有不同:
1. Go 中的数组是值类型,换句话说,如果你将一个数组赋值给另外一个数组,那么,实际上就是将整个数组拷贝一份。因此,在 Go 中如果将数组作为函数的参数传递的话,那效率就肯定没有传递指针高了。
2. 数组的长度也是类型的一部分,这就说明[10]int和[20]int不是同一种数据类型。并且Go 语言中数组的长度是固定的,且不同长度的数组是不同类型,这样的限制带来不少局限性。
3. 而切片则不同,切片(slice)是一个拥有相同类型元素的可变长序列,可以方便地进行扩容和传递,实际使用时比数组更加灵活,这也正是切片存在的意义。而且切片是引用类型,因此在当传递切片时将引用同一指针,修改值将会影响其他的对象。
三. 切片使用
切片定义方式
var a []int //nil切片,和nil相等,一般用来表示一个不存在的切片
var b []int{} //空切片,和nil不相等,一般用来表示一个空的集合
var c []int{1, 2, 3} //有3个元素的切片,len和cap都为3
var d = c[:2] //有2个元素的切片,len为2,cap为3
var e = c[:2:cap(c)] //有2个元素的切片,len为2,cap为3
var f = c[:0] //有0个元素的切片,len为0,cap为3
var g = make([]int, 3) //创建一个切片,len和cap均为3
var h = make([]int, 3, 6) //创建一个切片,len为3,cap为5
var i = make([]int, 0, 3) //创建一个切片,len为0,cap为3
从数组中切取切片
数组和切片是紧密相连的。切片可以用来访问数组的部分或全部元素,而这个数组称为切片的底层数组。切片的指针指向数组第一个可以从切片中访问的元素,这个元素并不一定是数组的第一个元素。
一个底层数组可以对应多个切片,这些切片可以引用数组的任何位置,彼此之前的元素可以重叠。
slice 操作符 s[i:j] 创建了一个新的 slice,这个新的 slice 引用了 s 中从 i 到 j-1 索引位置的所有元素。
如果表达式省略了 i,那么默认是s[0:j];如果省略了 j,默认是s[i:len(s)];
//创建一个数组
months := [...]string{1:"January", /*...*/, 12: "December"}
Q2 := months[4:7]
summer := months[6:9]
fmt.Println(Q2) //["April" "May" "June"]
fmt.Println(summer) //["June" "July" "August"]
月份名称字符串数组与其对应的两个元素重叠的 slice 图示
注意:切片与原数组或切片共享底层空间,修改切片会影响原数组或切片
迭代切片
切片可以用 range 迭代,但是要注意:如果只用一个值接收 range,则得到的只是切片的下标,用两个值接收 range,则得到的才是下标和对应的值。
//使用一个值接收range, 则得到的是切片的下标
for i := range months {
fmt.Println(i) //返回下标 0 1 ... 12
}
//使用两个值接收range,则得到的是下标和对应的值
for i, v := range months {
fmt.Println(i, v) //返回下标0 1 ... 12 和 值 "" "January" ... "December"
}
切片拷贝
使用copy内置函数拷贝两个切片时,会将源切片的数据逐个拷贝到目的切片指向的数组中,拷贝数量取两个切片的最小值。
例如长度为 10 的切片拷贝到长度为 5 的切片时,将拷贝 5 个元素。也就是说,拷贝过程中不会发生扩容。
copy 函数有返回值,它返回实际上复制的元素个数,这个值就是两个 slice 长度的较小值。
切片扩容-append 函数
//通过append()函数可以在切片的尾部追加 N 个元素
var a []int
a = append(a, 1) // 追加一个元素
a = append(a, 1, 2, 3) // 追加多个元素
a = append(a, []int{1, 2, 3}...) // 追加一个切片,注意追加切片时后面要加...
//使用 append()函数也可以在切片头部添加元素
a = append([]int{0}, a...) // 在开头添加一个元素
a = append([]int{1, 2, 3}, a...) // 在开头添加一个切片
注:从头部添加元素会引起内存的重分配,导致已有元素全部复制一次。因此从头部添加元素的开销要比从尾部添加元素大很多
//通过 append()函数链式操作从中间插入元素
a = append(a[:i], append([]int{x}, a[i:]...)...) //在第i个位置上插入x
a = append(a[:i], append([]int{1, 2, 3}, a[i:]...)...) //在第i个位置上插入切片
使用链式操作在插入元素,在内层 append 函数中会创建一个临式切片,然后将a[i:]内容复制到新创建的临式切片中,再将临式切片追加至a[:i]中。
通过 append()和 copy()函数组合从中间插入元素
使用这种方式可以避免创建过程中间的临式切片,也可以做到从中间插入元素
//中间插入一个元素
a = append(a, 0) //切片扩展一个空间
copy(a[i+1:], a[i:]) //a[i:]向后移动一个位置
a[i] = x //设置新添加的元素
//中间插入多个元素
a = append(a, x...) //为x切片扩展足够的空间
copy(a[i+len(x):], a[i:]) //a[i:]向后移动len(x)个位置
copy(a[i:], x) //复制新添加的切片
使用此方式虽然稍显复杂,但是可以减少创建中间临时切片的开销。
删除元素
很遗憾,Go 语言中并没有提供直接删除指定位置元素的方式。不过根据切片的性质,我们可以通过巧妙的拼接切片来达到删除指定数据的目的。
a = []int{1, 2, 3}
//删除尾部元素
a = a[:len(a) - 1] //删除尾部一个元素
a = a[:len(a) - N] //删除尾部N个元素
//删除头部元素
a = [1:] //删除开头1个元素
a = [N:] //删除开头N个元素
//删除中间元素
a = append(a[:i], a[i+1:]...) //删除中间一个元素
a = append(a[:i], a[i+N:]...) //删除中间N个元素
来源:https://blog.csdn.net/m0_63593747/article/details/125708684
猜你喜欢
- 升级背景:为了解决mysql低版本的漏洞,从mysql5.5升级到了8.0.11版本,再次升级到了8.0.17版本(从版本是2019.7.2
- 装饰器本质上是一个 Python 函数或类,它可以让其他函数或类在不需要做任何代码修改的前提下增加额外功能,装饰器的返回值也是一个函数/类对
- 序列化把对象(变量)从内存中变成可存储或传输的过程称之为序列化,在Python中叫pickling,在其他语言中也被称之为serializa
- python中的列表是可以直接进行逆序排列的,但是在 python中,逆序排列也是有一定规则的,一般是按升序排序,也就是从左到右。比如 li
- 在开发过程中往往需要配合单元测试,但是很多时候,单元测试需要依赖一些比较复杂的准备工作,比如需要依赖数据库环境,需要依赖网络环境,单元测试就
- 获取表字段:select * from user_tab_columns where Table_Name='用户表' or
- dim dr dr="2123123" dr1=Cint(dr) dr2=Clng(dr) 可参考如下函数说明: CIn
- 1、停止所有Oracle服务进入计算机管理,在服务中,找到oracle开头的所有服务,右击选择停止。快捷键:ctrl+shift+esc打开
- 经典鼠标控制左右滚动,图片间隔无缝滚动,悬停滚动,图片控制左右滚动JavaScript代码<!DOCTYPE html PUBLIC
- 1 端口映射举个例子来说明一下端口映射的作用。有A、B、C三台计算机,A、B互通,B、C互通,但是A、C不通,这个时候在C上开了一个Web服
- 本文实例讲述了Python多重继承的方法解析执行顺序。分享给大家供大家参考,具体如下:任何实现多重继承的语言都要处理潜在的命名冲突, 这种冲
- 目录项目地址功能概述效果图模块安装提交环境为python3.7 pyqt5==5.13.2 win10 一切正常!说一说大概的思路吧项目地址
- 0、前言评判一个算法的好坏的标准:时间复杂度空间复杂度1、归并排序算法是什么?冒泡排序(Bubble Sort)是一种建立在归并操作上面的一
- 问题描述给出一个整数数组 nums,请返回其中位数为偶数的数字的个数。示例 1:输入:nums = [12,345,2,6,7896]输出:
- body {font-family: Arial, sans-serif; }这是我迄今
- 为了实现Nao机器人与电脑端的TCP通信,于是研究了一下Python实现TCP通信,在网上也看到了很多例子,但大多都是在一台机器上验证。在两
- 我国移动互联网进入了飞速发展阶段,互联网人才日益受到企业的重视,其中PHP开发人才便是其中之一,在互联网旅游、金融、餐饮、娱乐、社交等一些新
- 本篇文章通过调用opencv里的函数简单的实现了对图像里特定颜色提取与定位,以此为基础,我们可以实现对特定颜色物体的前景分割与定位,或者特定
- Python标准库中的BaseHTTPServer模块实现了一个基础的HTTP服务器基类和HTTP请求处理类。这在文章python探索之Ba
- 这个我早就改好了一直没有放上来.现在发给大家用用注意这几个变量它们影响到提示框的效果代码:var rT=true;//允许图像过渡