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. Shell 基本常识

    Shell 进入命令行 启动 shell 常用命令 系统管理命令 处理数据命令 Linux 基础管理命令 用户管理 管理文件系统 软件包管理系统 使用容器管理软件 理解 shell 子 shell 环 ...

  2. 基于Udp通讯的Java局域网群聊小程序

    /**基于Udp通讯的Java局域网群聊小程序 */package com.UdpDemo; import java.net.*; import java.awt.*; import java.awt ...

  3. 一文详解 Linux Crontab 调度任务

    最近接到这样一个任务: 定期(每天.每月)向"特定服务器"传输"软件服务"的运营数据,因此这里涉及到一个定时任务,计划使用Python语言添加Crontab依赖 ...

  4. SpringBoot 项目中配置多个 Jackson 的 ObjectMapper ,以及配置遇到的坑

    目录 问题说明 原因排查分析 结论总结 Jackson 自动装配分析 问题说明 我们都知道,SpringBoot 项目中,如果引入了 Jackson 的包,哪怕不配置,SpringBoot 也会帮我们 ...

  5. 闻其声而知雅意,基于Pytorch(mps/cpu/cuda)的人工智能AI本地语音识别库Whisper(Python3.10)

    前文回溯,之前一篇:含辞未吐,声若幽兰,史上最强免费人工智能AI语音合成TTS服务微软Azure(Python3.10接入),利用AI技术将文本合成语音,现在反过来,利用开源库Whisper再将语音转 ...

  6. 双目测距+点云——使用MiddleBurry数据集的图片

    效果 输入: 左图 右图 输出: 视差图 深度图 实现了鼠标点击图片中的位置,显示其深度. 点云 其他例子点云: bicycle motorcycle 使用自己的双目摄像头拍摄的图片: bottle ...

  7. Longbow.Tasks

    Longbow.Tasks 概述 大体分为了Scheduler(调度任务),Storage(持久化),Trigger(触发器),Task(任务)和逻辑模块,大体流程为通过逻辑代码进行实例化相关类,根据 ...

  8. 【分析笔记】全志方案通过命令行操作 GPIO 口(带源码分析)

    前言说明 在项目开发初期,很经常会需要临时操作某个GPIO来验证某些功能,可以通过编写一个简单的驱动程序来操作,但更方便的是可以通过命令行直接操作 GPIO ,这样不需要经过编写代码.编译驱动.推入文 ...

  9. App测试Android的闪退总结

    Android的闪退有三种情况: 第一种:没有任何弹框提示,直接退出 第二种:有弹框提示程序异常 第三种:ANR无响应 三种情况的日志提交和检索方法:  第一种情况:是底层C挂了 **首先:提交客户端 ...

  10. 【Oculus Interaction SDK】(六)实体按钮 && 按压交互

    前言 这篇文章是[Oculus Interaction SDK]系列的一部分,如果发现有对不上的对方,可以回去翻看我之前发布的文章,或在评论区留言.如果文章的内容已经不适用于新版本了,也可以直接联系我 ...