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. hashlib 模块 subprocess 模块 logging日志模块

    今日内容 hashlib加密模块 1.何为加密 将明文数据处理成密文数据 让人看不懂 2.为什么加密 保证数据的安全 3.如何判断数据是否加密的 一串没有规律的字符串(数字.字母.符号) 4.密文的长 ...

  2. Hugging Face 开源库介绍

    Hugging Face 的开源生态今年成长迅速,timm 成为新加入的成员.diffusers.evaluate 以及 skops 等各种库蓬勃发展. Transformers Transforme ...

  3. ChatGPT开发实战

    1.概述 前段时间使用体验了ChatGPT的用法,感受到ChatGPT的强大,通过搜索关键字或者输入自己的意图,能够快速得到自己想要的信息和结果.今天笔者将深挖一下ChatGPT,给大家介绍如何使用C ...

  4. 特定领域知识图谱融合方案:文本匹配算法(Simnet、Simcse、Diffcse)

    特定领域知识图谱融合方案:文本匹配算法(Simnet.Simcse.Diffcse) 本项目链接:https://aistudio.baidu.com/aistudio/projectdetail/5 ...

  5. 如何通过Java代码向Word文档添加文档属性

    Word文档属性包括常规.摘要.统计.内容.自定义.其中摘要包括标题.主题.作者.经理.单位.类别.关键词.备注等项目.属性相当于文档的名片,可以添加你想要的注释.说明等.还可以标注版权. 今天就为大 ...

  6. touchke变化值小的解决办法

    方法一,提高主频 方法二,减小充电时间. 方法三,充电电流减半(具体看RM手册touchkey章节) 建议测试时采样值维持在3000-4000 其实以上操作就是增大Y轴间隔,以增大按下和未按下时的采样 ...

  7. 12月2日内容总结——边框属性,display属性,css盒子模型,浮动、溢出、定位、z-index属性和建议博客页面搭建

    目录 一.边框 边框简介 border-style--边框样式 border-width--边框宽度 border-color--边框颜色 二.display属性 三.CSS盒子模型 概念 margi ...

  8. 构建api gateway之 如何给openresty打patch

    如何给openresty打patch 由于很多功能实现的限制,我们不得不修改openresty,但我们又不一定能持续维护一个 openresty 分支,所有有了patch 这一操作. patch是怎么 ...

  9. CSS常用属性(2)

    (4) position(定位) fixed 一般用来写网页顶端的固定导航条,或者两侧的菜单. <!--对于块级标签来说加上position:fixed之后,该div就不会占一整行,一般需要手动 ...

  10. SpringBoot2.6.x及以上版本整合swagger文档

    SpringBoot的版本更新中引入了一些新的特性,并且Swagger的版本更新也同样引入了很多新的东西,这样就造成了许多配置无法实现一一对应的情况,因此高版本的SpringBoot集成Swagger ...