Go数组和切片你不知道的区别
开篇语
数组和切片是两种不同的数据结构,比较常见,在Go语言中同时存在,今天我们就一起来看看他们在使用方式上,原理上的一些区别?
数组
在Go语言中,数组是一种具有相同类型固定大小的一种数据结构。
我们先来看看数组的使用,数组类型声明时的方式是 []T ,前面的[]指定数组的大小,T指定数组的类型,如下我们声明了一下数组,数组的大小是3,在没指定数组初始值时数组默认初始值是{0,0,0}
array1 := [3]int{}
//我们可以通过如下方式给数组赋值
array1[0] = 1
array1[1] = 2
array1[2] = 3
//下面这种也是数组声明的一种方式,并且初始化数组的值为{1,2}
array2 := [2]int {1,2}
思考一下前面我们array1赋值给array2对吗?记住,这种方式是错误的,在Go语言中只有大小相等,类型相同的数组才是同类型的数组,之间才可以相互赋值,如下截图,我们可以看见array1赋值给array2时编译器报错
array2 = array1
看上面的图,我们再思考一个问题,我们把array3 赋值给array2后,修改了array3下标为0的值等于6,请问打印的结果是?这个问题考验的是我们把array3赋值给array2后,修改了array3的值,会对array2产生影响吗?答案是不会,记住,在Go中,数组属于基本类型,他们之间的赋值,传递是属于值拷贝,同样的,如果将数组作为参数在函数间传递,也是属于值拷贝
第一种结果:0,0,0; 4,5; 6,5
第二种结果:0,0,0; 6,5; 6,5
数组的长度,我们声明了一个数组,那如何获取数组的长度呢?通过len(array4)
获取数组的长度
array4 := [2]int {1,2}
l := len(array4)
fmt.Println(""l)
多维数组的声明,多为数组可以想象成就是多个一维数组,如下声明了一个二维数组,代表有两个一维数组,每个一维数组的长度是2
array4 := [2][2]int{}
array6 := [2][2]int{{1,2},{3,4}}
对数组的访问和遍历
//访问数组中的元素
array4 := [2]int {1,2}
//访问数组下标为0处的值并打印
fmt.Println(array4[0])
//通过range遍历数组,
//i代表数组的下标,
//v代表数组下标为i处的值
for i,v := range array4{
fmt.Println(i,v)
}
array5 := [2][2]int{{1,2},{3,4}}
for i,tempArray := range array5{
//此时tempArray是一维数组
//再通过range 遍历tempArrayy一维数组
for j,v := range tempArray{
fmt.Println(j,v)
}
}
切片
在Go语言中,切片是数组的一种高级运用,相对于数组,切片是一种更加方便,灵活,高效的数据结构。,切片并不存储任何元素而只是对现有数组的引用(不是值拷贝,是指针)
切片的声明方式有以下几种
通过数组创建一个切片
array1 := [3]int{1,2,3}
//将数组下标从1处到下标2处的元素转换为一个切片(前闭后开)
slice1 := array1[1:2]
直接声明一个切片
//下面代码直接出初始化一个切片 (这里大家有个疑问,我不管怎么看都觉得它是一个数组啊)
//记住,再go语言中,区别一个变量是数组还是切片,就看有没有定义长度
//有定义长度就是数组,如array1,没定义就是切片 如slice2
//我们也通过fmt.Println(reflect.TypeOf(array1),reflect.TypeOf(slice2))
//上面这代码打印的结果是[3]int,[]int,可以看到前者有长度,后者没有
slice2 := []int{1,2,3}
通过make函数创建一个切片,也是最常用的
//[]int,指定切片的类型,3是切片的长度,6是切片的容量
slice3 := make([]int,3,6)
通过切片生成一个切片
//声明一个切片
slice4 := []int {1,2,3,4,5,6}
//通过slice4创建一个切片,元素是slice4下标从0到1(不包含1)的元素
slice5 := slice4[0:1]
//通过slice4创建一个切片,元素是slice4下标从0到末尾的元素
slice6 := slice4[1:]
//通过slice4创建一个切片,元素是slice4下标从0到3的元素
slice7 := slice4[:3]
上面我们介绍了切片的几种常见构造方式,接下来我们看看如何操作切片
slice3 := make([]int,3,6)
//给切片赋值
slice3[0] = 0
slice3[1] = 1
slice3[2] = 2
//通过len([]Type) cap([]Type)两个函数查看切片的长度和容量
fmt.Println(len(slice3),cap(slice3))
结果:3,6
思考一下我们能给上面切片slice3下标为3处赋值吗 ? slice3[3] = 3
,答案是不能的,虽然我们定义了切片的长度是3,容量是6,但对切片的操作是以长度为准的,如果已经赋值到最大长度了,怎么办呢?切片为我们提供了append([]Type, elems...Type)[]Type
方法向切片中追加元素 []Type代表传入一个切片,elems代表追加的元素,可以传多个。
//想slice3 切片追加三个元素,返回一个新的切片
slice3 = append(slice3,3,4,5)
//此时再次查看切片的长度和容量
fmt.Println(len(slice3),cap(slice3))
结果: 6, 6 切片的长度和容量保持一致了
//思考一下,我们再次append能给切片追加元素吗? 肯定可以的,前面说过切片是可扩长的
slice3 = append(slice3,7,8,9)
//此时再次查看切片的长度和容量
fmt.Println(len(slice3),cap(slice3))
结果:9, 12
发现了什么?在切片容量满时,切片的扩容时翻倍的,也就是新的切片的容量时原切片的容量的2倍
知道了切片的追加,长度,容量,那么如何删除切片里的元素呢?如果你在看通过切片创建一个切片时思考过,你就知道如何删除切片中的元素了
//我们创建了一个切片,有四个元素,下标命名为0,1,2,3
slice11 := []int{1,2,3,4}
//假设我们要删除下标为0的元素,这段代码的含义是
创建一个空的切片 slice11[:0]
创建一个从下标1到末尾元素的切片 slice11[1:]
给空切片添加元素并返回一个新的切片
slice12 := append(slice11[:0],slice11[1:]...)
//同上我们得出删除下标为i的元素的切片的公式时
sliceTemp := append(slice11[:i],slice[i+1:]...)
下图是切片删除的一个过程
数组和切片的底层存储
我们看下图分析
基于上图我们会发现,切片的底层就是数组,切片是通过指针的形式指向不同数组的位置从而形成不同的切片,切片对本身元素的修改,也会影响到数组和其它的切片。看下面代码,大家猜一猜输出结果
array11 := [5]int{1,2,3,4,5}
slice11 := array11[0:3]
slice11[0] = 10
sliceTemp := append(array11[:2],array11[3:]...)
slice11[0] = 11
fmt.Println(array11,slice11,sliceTemp)
//输出结果:[11 2 4 5 5] [11 2 4] [11 2 4 5]
欢迎大家关注微信公众号:“技术人技术事”,更多精彩期待你的到来
![](https://img2018.cnblogs.com/blog/706455/201908/706455-20190821135940196-775543041.jpg)
,
Go数组和切片你不知道的区别的更多相关文章
- Golang数组和切片的区别
大纲 数组是固定大小 切片不是动态数组,可以扩容 区别 定义方式不一样 初始化方法不一样 package main import "fmt" func main() { // -- ...
- golang中数组与切片的区别
初始化:数组需要指定大小,不指定也会根据初始化的自动推算出大小,不可改变 数组: a := [...],,} a := [],,} 切片: a:= [],,} a := make([]) a := m ...
- 换个语言学一下 Golang (6)——数组,切片和字典
在上面的章节里面,我们讲过Go内置的基本数据类型.现在我们来看一下Go内置的高级数据类型,数组,切片和字典. 数组(Array) 数组是一个具有相同数据类型的元素组成的固定长度的有序集合.比如下面的例 ...
- go语言的数组和切片区别
这里不介绍数组和切片的使用技巧,主要看下2者的区别. 首先看下它们的定义: 数组:类型 [n]T 表示拥有 n 个 T 类型的值的数组. 切片:类型 []T 表示一个元素类型为 T 的切片. 看一个数 ...
- GoLang笔记-数组和切片,本质是就是长度不可变的可变的区别
数组 Arrays 数组是内置(build-in)类型,是一组同类型数据的集合,它是值类型,通过从0开始的下标索引访问元素值.在初始化后长度是固定的,无法修改其长度.当作为方法的入参传入时将复制一份数 ...
- Python: 列表、数组及迭代器切片的区别及联系
1. 对列表和数组进行切片 1.1 切片索引 众所周知,Python中的列表和numpy数组都支持用begin: end语法来表示[begin, end)区间的的切片索引: import numpy ...
- GO语言总结(3)——数组和切片
上篇博文简单介绍了一下Go语言的基本类型——GO语言总结(2)——基本类型,本篇博文开始介绍Go语言的数组和切片. 一.数组 与其他大多数语言类似,Go语言的数组也是一个元素类型相同的定长的序列. ( ...
- Go - 数组 和 切片(array、slice)
一.数组 与其他大多数语言类似,Go语言的数组也是一个元素类型相同的定长的序列. (1)数组的创建 数组有 3 种创建方式: 1) [length]Type 2) [length]Type{value ...
- GO语言数组和切片实例详解
本文实例讲述了GO语言数组和切片的用法.分享给大家供大家参考.具体分析如下: 一.数组 与其他大多数语言类似,Go语言的数组也是一个元素类型相同的定长的序列. (1)数组的创建. 数组有3种创建方式: ...
随机推荐
- Java 对象序列化机制详解
对象序列化的目标:将对象保存到磁盘中,或允许在网络中直接传输对象. 对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久的保存在磁盘上,通过网络将这种二进制流传 ...
- Beta版是什么意思
外部测试版的意思. 软件会出现三种版本 1.alpha内部测试版本,极不稳定,一般也不会出现的公众视线,仅供内部测试人员测试用. 2.beta公共测试版,就是对外发布软件的测试版,收集公众的意见和建议 ...
- Python 科学计算库numpy
Numpy基础数据结构 NumPy数组是一个多维数组对象,称为ndarray.其由两部分组成: 实际的数据 描述这些数据的元数 # 多维数组ndarray import numpy as np ar ...
- [C++] 获取IE代理服务器的账号密码
很多程序需要使用'浏览器设置'的代理服务器,IE设置的代理服务器有可能是需要账号密码的.怎样编程获取浏览器设置的代理服务器的账号密码呢? InternetQueryOption(NULL, INTER ...
- MAMP "403 Forbidden You don't have permission to access / on this server."
2015年01月22日 17:27:31 阅读数:3488 用MAMP搭建本地服务器的时候,设置好ip和端口等属性之后,浏览器访问,报 403错误: Forbidden You don't have ...
- 【js】vue 2.5.1 源码学习 (七) 初始化之 initState 响应式系统基本思路
大体思路(六) 本节内容: 一.生命周期的钩子函数的实现 ==> callHook(vm , 'beforeCreate') beforeCreate 实例创建之后 事件数据还未创建 二.初始化 ...
- UVa 1374 - Power Calculus——[迭代加深搜索、快速幂]
解题思路: 这是一道以快速幂计算为原理的题,实际上也属于求最短路径的题目类型.那么我们可以以当前求出的幂的集合为状态,采用IDA*方法即可求解.问题的关键在于如何剪枝效率更高.笔者采用的剪枝方法是: ...
- MySQL视图操作命令详解
内容目录 创建视图 删除视图 修改视图 查看视图 §创建视图 在MySQL中,创建视图的完整语法如下: CREATE [OR REPLACE] [ALGORITHM = {UNDEFINED | ME ...
- H3C 各类路由默认优先级
- 2019-4-10-win10-uwp-自定义标记扩展
title author date CreateTime categories win10 uwp 自定义标记扩展 lindexi 2019-04-10 09:46:13 +0800 2019-04- ...