1.切片的定义

切片(slice)是对数组一个连续片段的引用,所以切片是一个引用类型。

切片的使用与数组类似,遍历,访问切片元素等都一样。切片是长度是可以变化的,因此切片可以看做是一个动态数组。

  • 一个切片由三个部分构成:底层数组的指针、长度(len)和容量(cap),指针指向该切片自己第一个元素对应的底层数组元素的内存地址,容量可以容纳最多元素的个数,默认为2*len。
  • cap可以求出slice最大扩张容量,不能超出数组限制。0 <= len(slice) <= len(array),其中array是slice引用的数组。

2.切片初始化

2.1 定义一个切片,然后让切片去引用一个已经创建好的数组。

package main

import "fmt"

func main() {
var arr1 = [8]int{0, 1, 2, 3, 4, 5, 6, 7} //定义数组arr1,长度为8
var slice []int = arr1[0:4] //可以简写为slice := arr1[0:4]
slice1 := arr1[0:4] //从0下标开始,到4下标结束,不包含下标为4的值。
slice2 := arr1[:5] //从开头开始(0下标),到下标为5结束,不包含下标为5的值。
slice3 := arr1[6:] //从6下标开始,到数组末尾结束。
slice4 := arr1[:] //获取全部数组。
fmt.Printf("slice的值为:%v,slice的长度为:%v,slice容量为:%v\n", slice, len(slice), cap(slice))
fmt.Printf("slice1的值为:%v,slice1的长度为:%v,slice1容量为:%v\n", slice1, len(slice1), cap(slice1))
fmt.Printf("slice2的值为:%v,slice2的长度为:%v,slice2容量为:%v\n", slice2, len(slice2), cap(slice2))
fmt.Printf("slice3的值为:%v,slice3的长度为:%v,slice3容量为:%v\n", slice3, len(slice3), cap(slice3))
fmt.Printf("slice4的值为:%v,slice4的长度为:%v,slice4容量为:%v\n", slice4, len(slice4), cap(slice4))
}

执行结果

slice的值为:[0 1 2 3],slice的长度为:4,slice容量为:8
slice1的值为:[0 1 2 3],slice1的长度为:4,slice1容量为:8
slice2的值为:[0 1 2 3 4],slice2的长度为:5,slice2容量为:8
slice3的值为:[6 7],slice3的长度为:2,slice3容量为:2
slice4的值为:[0 1 2 3 4 5 6 7],slice4的长度为:8,slice4容量为:8

2.2 定一个切片,直接就指定具体数组

package main

import "fmt"

func main() {
a := []int{} //空切片,和nil不相等,一般用来表示一个空的集。
b := []int{0, 1, 2} //有3个元素的切片。
fmt.Printf("a的值为:%v,a的长度为:%v,a容量为:%v\n", a, len(a), cap(a))
fmt.Printf("b的值为:%v,b的长度为:%v,b容量为:%v\n", b, len(b), cap(b))
}

执行结果

a的值为:[],a的长度为:0,a容量为:0
b的值为:[0 1 2],b的长度为:3,b容量为:3

2.3. make创建切片

基本语法: var切片名[]type = make([]type, len, cap) //[]type为切片类型,len为切片长度,cap为切片容量

package main

import "fmt"

func main() {
slice1 := make([]int, 5, 10) //定义长度为5,容量为10的切片,没有赋值,所以切片的值都为int类型的默认值0
fmt.Printf("slice的值为:%v,slice的长度为:%v,slice容量为:%v\n", slice1, len(slice1), cap(slice1))
slice1[3] = 10 //给slice切片下标为3,赋值为10.
fmt.Printf("slice的值为:%v\n", slice1)
slice2 := make([]string, 4) //不指定容量,默认容量跟长度一致
fmt.Printf("slice2的值为:%v,slice2的长度为:%v,slice2容量为:%v\n", slice2, len(slice2), cap(slice2))
}

执行结果

slice的值为:[0 0 0 0 0],slice的长度为:5,slice容量为:10
slice的值为:[0 0 0 10 0]
slice2的值为:[ ],slice2的长度为:4,slice2容量为:4

3. 切片的遍历

3.1 for循环遍历

package main

import "fmt"

func main() {
var slice1 = []int{1, 2, 3, 4, 5}
for i := 0; i < len(slice1); i++ {
fmt.Printf("下标为%v的值为:%v\n", i, slice1[i])
}
}

执行结果

下标为0的值为:1
下标为1的值为:2
下标为2的值为:3
下标为3的值为:4
下标为4的值为:5

3.2 for range遍历

package main

import "fmt"

func main() {
var slice1 = []int{1, 2, 3, 4, 5}
for k1, v1 := range slice1 {
fmt.Printf("下标为%v的值为:%v\n", k1, v1)
}
}

执行结果

下标为0的值为:1
下标为1的值为:2
下标为2的值为:3
下标为3的值为:4
下标为4的值为:5

4.切片的内存

切片下标为0的内存地址,对应底层数组的开始位置的内存地址,当修改切片的值时,因为切片的内存地址和数组中截取的数据内存地址相同,数组的值也会修改。

package main

import "fmt"

func main() {
var arr1 = [8]int{1, 2, 3, 4, 5, 6, 7, 8}
var slice1 = arr1[1:4] //取arr1数组下标为1,2,3的,[2,3,4]
fmt.Printf("arr1的值为:%v,arr1的内存地址为:%p\n", arr1, &arr1[1])
fmt.Printf("slice1的值为:%v,slice1的内存地址为:%p\n", slice1, &slice1[0])
slice1[0] = 10
fmt.Printf("修改后arr1的值为:%v\n", arr1)
fmt.Printf("修改后slice1的值为:%v\n", slice1)
}

执行结果

arr1的值为:[1 2 3 4 5 6 7 8],arr1的内存地址为:0xc00001a308
slice1的值为:[2 3 4],slice1的内存地址为:0xc00001a308
修改后arr1的值为:[1 10 3 4 5 6 7 8]
修改后slice1的值为:[10 3 4]

5. append方法

package main

import "fmt"

func main() {
slice1 := []int{1, 2, 3, 4, 5, 6, 7, 8}
fmt.Printf("slice1切片的值为:%v,slice1的长度为%v,slice1的容量为:%v\n", slice1, len(slice1), cap(slice1))
slice1 = append(slice1, 9) //在切片slice1后面添加一个元素9
fmt.Printf("slice1切片的值为:%v,slice1的长度为%v,slice1的容量为:%v\n", slice1, len(slice1), cap(slice1))
slice1 = append(slice1, 10, 11, 12) //在切片slice1后面添加三个元素,10,11,12
fmt.Printf("slice1切片的值为:%v,slice1的长度为%v,slice1的容量为:%v\n", slice1, len(slice1), cap(slice1))
slice2 := [][]int{[]int{1, 2, 3}} //定义slice2,里面的数据类型为切片
fmt.Printf("slice2切片的值为:%v,slice2的长度为%v,slice2的容量为:%v\n", slice2, len(slice2), cap(slice2))
slice2 = append(slice2, slice1) //将slice1切片追加到slice2里面
fmt.Printf("slice2切片的值为:%v,slice2的长度为%v,slice2的容量为:%v\n", slice2, len(slice2), cap(slice2))
}

执行结果

slice1切片的值为:[1 2 3 4 5 6 7 8],slice1的长度为8,slice1的容量为:8
slice1切片的值为:[1 2 3 4 5 6 7 8 9],slice1的长度为9,slice1的容量为:16
slice1切片的值为:[1 2 3 4 5 6 7 8 9 10 11 12],slice1的长度为12,slice1的容量为:16
slice2切片的值为:[[1 2 3]],slice2的长度为1,slice2的容量为:1
slice2切片的值为:[[1 2 3] [1 2 3 4 5 6 7 8 9 10 11 12]],slice2的长度为2,slice2的容量为:2

6. copy方法

package main

import "fmt"

func main() {
slice1 := []int{1, 2, 3, 4, 5, 6, 7, 8}
fmt.Printf("slice1切片的值为:%v\n", slice1)
slice2 := []int{9, 10}
fmt.Printf("slice2切片的值为:%v\n", slice2)
//内置函数copy将切片slice2中的值拷贝到slice1中将slice1中的前len(slice2)个的元素值覆盖掉。
//slice1和slice1的数据空间是相互隔离的,互不影响。若将slice1[1]设置为2,则slice2[1]仍为10而不随着若将slice1[1]的改变而改变。
copy(slice1, slice2) //将slice2元素copy到slice1
fmt.Printf("slice1切片的值为:%v\n", slice1) //注意:由于切片是引用类型,所以slice3和slice4其实都指向了同一块内存地址。
//修改slice4的同时slice3的值也会发生变化。
slice3 := []int{1, 2, 3}
slice4 := slice3
fmt.Printf("slice3切片的值为:%v,slice3[0]的内存地址为:%p,slice3[1]的内存地址为:%p,slice3[2]的内存地址为:%p,\n", slice3, &slice3[0], &slice3[1], &slice3[2])
fmt.Printf("slice4切片的值为:%v,slice4[0]的内存地址为:%p,slice4[1]的内存地址为:%p,slice4[2]的内存地址为:%p,\n", slice4, &slice4[0], &slice4[1], &slice4[2])
slice4[0] = 10
fmt.Printf("slice3的值为:%v\n", slice3)
fmt.Printf("slice4的值为:%v\n", slice4)
}

执行结果

slice1切片的值为:[1 2 3 4 5 6 7 8]
slice2切片的值为:[9 10]
slice1切片的值为:[9 10 3 4 5 6 7 8]
slice3切片的值为:[1 2 3],slice3[0]的内存地址为:0xc000010120,slice3[1]的内存地址为:0xc000010128,slice3[2]的内存地址为:0xc000010130,
slice4切片的值为:[1 2 3],slice4[0]的内存地址为:0xc000010120,slice4[1]的内存地址为:0xc000010128,slice4[2]的内存地址为:0xc000010130,
slice3的值为:[10 2 3]
slice4的值为:[10 2 3]

golang 切片(slice)的更多相关文章

  1. golang切片slice

    切片slice是引用类型 len()函数获取元素的个数 cap()获取数组的容量 1.申明方式 (1)var a []int 与数组不同的是他不申明长度(2)s2 := make([]int, 3, ...

  2. Golang 入门 : 切片(slice)

    切片(slice)是 Golang 中一种比较特殊的数据结构,这种数据结构更便于使用和管理数据集合.切片是围绕动态数组的概念构建的,可以按需自动增长和缩小.切片的动态增长是通过内置函数 append( ...

  3. 转 Golang 入门 : 切片(slice)

    https://www.jianshu.com/p/354fce23b4f0 切片(slice)是 Golang 中一种比较特殊的数据结构,这种数据结构更便于使用和管理数据集合.切片是围绕动态数组的概 ...

  4. golang基础---Slice切片

    切片Slice在go语言中是单独的类型(指向底层的数组),不同于python(对可迭代对象操作的工具),注意区分数组和slice的区别 定义一个空slice,格式var s []int,这种既没有长度 ...

  5. Go 灵活多变的切片Slice

    我们知道数组定义好之后其长度就无法再修改,但是,在实际开发过程中,有时候我们并不知道需要多大的数组,我们期望数组的长度是可变的, 在 Go 中有一种数据结构切片(Slice) 解决了这个问题,它是可变 ...

  6. [Golang]-1 Slice与数组的区别

    目录 数组 1.创建数组: 2.数组是值拷贝传递: 切片(slice) 1.首先看看slice的源码结构: 2.slice的创建: 3.slice使用make创建 4.切片作为参数传递 5.Golan ...

  7. go 数组(array)、切片(slice)、map、结构体(struct)

    一 数组(array) go语言中的数组是固定长度的.使用前必须指定数组长度. go语言中数组是值类型.如果将数组赋值给另一个数组或者方法中参数使用都是复制一份,方法中使用可以使用指针传递地址. 声明 ...

  8. 在python&numpy中切片(slice)

     在python&numpy中切片(slice) 上文说到了,词频的统计在数据挖掘中使用的频率很高,而切片的操作同样是如此.在从文本文件或数据库中读取数据后,需要对数据进行预处理的操作.此时就 ...

  9. golang切片数据结构解释

    1. 切片:切片是数组的一个引用,因此切片是引用类型 func main() { var arr = [6]int{1, 2, 3, 4, 5} var slice = arr[1:] fmt.Pri ...

  10. golang切片类型

    切片slice 其本身并不是数组,它指向底层的数组 作为变长数组的替代方案,可以关联底层数组的局部或全部 为引用类型 可以直接创建或从底层数组获取生成 使用len()获取元素个数,cap()获取容量 ...

随机推荐

  1. OPPO 后端开发 一、二面面经

    你好,我是 Guide,看了这么多面试成功的经验分享,今天来看一个读者分享的 Oppo 秋招面试失败经历. 面经合集请看:Java面试题&面经精选集. 下面是正文(文中的我为读者本人). 个人 ...

  2. ZXing CaptureActivity黑屏问题

    关于zxing captureActivity黑屏的问题,我在网上搜索一下,结果发现几乎没有这方面的资料.后来自己用了半天时间,独步跟踪调试,查看相机类的代码,最后发现了一点问题,就是关闭相机的时候没 ...

  3. NG-ZORRO + Angular11使用Echarts实现柱折线图-折柱混合,并给图表添加点击打印图表数据!!!详细代码

    先上效果图 HTML代码 <div echarts #myEchart [options]="option"></div> ts代码 import { Co ...

  4. 记一次简单的诈骗网站Getshell

    前言:在放假期间接到一个诈骗电话.然后说京东金条利率过高让我处理下(在疫情开放期间京东客服基本上是没有人工客服),然后就慢慢的被拉入钉钉会议,然后骗子给网站的时候发现域名不对就判定成了骗子就找理由有事 ...

  5. Unity之UGUI鼠标进入离开&&拖拽实现

    Unity之UGUI鼠标进入离开&&拖拽实现 前言: __小黑最近在写项目的时候就有个疑惑,UGUI中的Button组件,他的点击事件是怎么实现的!?我们自己能不能写一个!?之后在项目 ...

  6. inline的作用

    1:inline可以跳过调用,直接引用,类似与直接将函数中的代码拿到当前函数中一样 2:在.h中函数重复的时候可以用inline来解决冲突问题

  7. Time Series Analysis (Best MSE Predictor & Best Linear Predictor)

    Time Series Analysis Best MSE (Mean Square Error) Predictor 对于所有可能的预测函数 \(f(X_{n})\),找到一个使 \(\mathbb ...

  8. countdownlatch应用场景

    场景1 让多个线程等待:模拟并发,让并发线程一起执行 为了模拟高并发,让一组线程在指定时刻(秒杀时间)执行抢购,这些线程在准备就绪后,进行等待(CountDownLatch.await()),直到秒杀 ...

  9. vscode环境配置(C/C++)

    一.MinGW和vscode的简单了解 1.MinGW是什么? MinGW(Minimalist GNU on Windows).它实际上是将经典的开源 C语言 编译器 GCC 移植到了 Window ...

  10. kali linux生成密码字典方法

    kali linux生成密码字典方法 所谓的密码字典主要是配合密码破解软件所使用,密码字典里包括许多人们习惯性设置的密码.这样可以提高密码破解软件的密码破解成功率和命中率,缩短密码破解的时间.当然,如 ...