编程技术是改变世界的力量。
本站
当前位置:网站首页 > 后端语言 > 正文

爱上开源之golang入门至实战第四章-切片(Slice)

gowuye 2024-04-22 14:02 12 浏览 0 评论

前言

Go 数组的长度不可改变,在特定场景中这样的集合就不太适用,Go 中提供了一种灵活,功能强悍的内置类型切片("动态数组"),与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大。

在go语言里,切边是一个应用极为广泛的数据对象;所以在学习golang的过程中,一定要好好地掌握切片的相关知识。

4.2.2.1 声明切片

你可以声明一个未指定大小的数组来定义切片:

var slice_01 []type

在语法上和上面的数组比较的相似;差别就在于切片不需要说明长度。

也可以使用 make() 函数来创建切片:

var slice_01 []type = make([]type, len)

或为

slice_01 := make([]type, len)

在切片的make声明和初始话的方式中;也可以指定容量,

比如

make([]T, length, capacity)

其中 capacity 为可选参数。通过上面的方式就可以声明和初始话一个容量大小为capacity,当前长度为length的切片,切片的用法如何使用过python语言的话,这个切片的数据类型可以实现的功能基本上和python语言里slice函数的非常的相似

需要说明,slice 并不是数组或数组指针。它通过内部指针和相关属性引?数组?段,以实现变??案。

runtime.h

#runtime.h

struct Slice

{ // must not move anything

 byte* array; // actual data

 uintgo len; // number of elements

 uintgo cap; // allocated number of elements

};

以上是golang里slice的源代码片段;可以通过这个slice的结构体源代码的定义,发现在golang里,slice是通过内部属性和指针的方式,来实现了变长的方案。

? 引?类型。但??是结构体,值拷?传递。

? 属性 len 表?可?元素数量,读写操作不能超过该限制。

? 属性 cap 表?最?扩张容量,不能超出数组限制。

? 如果 slice == nil,那么 len、cap 结果都等于 0。

4.2.2.2 切片初始化

slice_01 :=[] int {1,2,3 }

通过初始化语句:=直接进行初始化, 其中[] 表示是切片类型,{1,2,3} 初始化值依次是 1,2,3,其 cap=len=3。通过以上语句,实现了初始化slice_01对象为切片对象,并且长度和容量都为3;其中元素依次为1,2,3的int切片。



4.2.2.3 len和cap

切片是可索引的,并且可以由 len() 方法获取长度。切片提供了计算容量的方法 cap() 可以测量切片最长可以达到多少。

x := make([]int,3,5)
fmt.Printf("len=%d cap=%d slice=%v**\n**",len(x),cap(x),x)


====OUTPUT====
len=3 cap=5 slice=[0 0 0]

一个切片在未初始化之前默认为 nil,长度为 0,如下:

var x []int
fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)


====OUTPUT====
len=0 cap=0 slice=[]

4.2.2.4 slice

s := arr[startIndex:endIndex] 

将 arr 中从下标 startIndex 到 endIndex-1 下的元素创建为一个新的切片。

s := arr[startIndex:] 

默认 endIndex 时将表示一直到arr的最后一个元素。

s := arr[:endIndex] 

默认 startIndex 时将表示从 arr 的第一个元素开始。

样例

data := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}

expression  slice                   len     cap     
------------+----------------------+------+-------
data[:6:8]  [0 1 2 3 4 5]           6       8       
data[5:]    [5 6 7 8 9]             5       5 
data[:3]    [0 1 2]                 3       10 
data[:]     [0 1 2 3 4 5 6 7 8 9]   10      10
data[:11:12] Error  

读写操作实际?标是底层数组,只需注意索引号的差别。

data := [...]int{0, 1, 2, 3, 4, 5}
s := data[2:4]
s[0] += 1020
s[1] += 2020
fmt.Println(s)
fmt.Println(data)

输出:

[1022 2023]
[0 1 1022 2023 3 4 5]
s1 := s[startIndex:endIndex] 

通过切片 s 初始化切片 s1。

对于是基于已有 slice 创建新 slice 对象,特别注意要保证切片的 cap 允许范围内调整属性。

s := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
s1 := s[2:5] // [2 3 4]         len=3  cap=8
s2 := s1[2:6:7] // [4 5 6 7]    len=3  cap=5
s3 := s2[3:6] // Error

切片操作后新对象依旧指向原底层数组。

    s := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
    s1 := s[2:5] // [2 3 4]
    s1[2] = 1020
    fmt.Println(s1)
    s2 := s1[2:6] // [1020 5 6 7]
    s2[0] = 2010
    s2[3] = 2020
    fmt.Println(s2)
    fmt.Println(s)

====OUTPUT====

[2 3 1020]
[2010 5 6 2020]
[2 3 2010]
[0 1 2 3 2010 5 6 2020 8 9]


4.2.2.5 append

向 slice 尾部添加数据,返回新的 slice 对象。

s := make([]int, 0, 5)
fmt.Printf("%p\n", &s)
s2 := append(s, 1)
fmt.Printf("%p\n", &s2)
fmt.Println(s, s2)

====OUTPUT=====
0xc000004498
0xc0000044c8
[] [1]
data := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
s := data[:3]
s2 := append(s, 100, 200) // 添加多个值。
fmt.Println(data)
fmt.Println(s)
fmt.Println(s2)

====OUTPUT=====
[0 1 2 100 200 5 6 7 8 9]
[0 1 2]
[0 1 2 100 200]

?旦超出原 slice.cap 限制,就会重新分配底层数组,即便原数组并未填满。

data := [...]int{0, 1, 2, 3, 4, 10: 0}
s := data[:2:3]
s = append(s, 100, 200) // ?次 append 两个值,超出 s.cap 限制。
fmt.Println(s, data) // 重新分配底层数组,与原数组?关。
fmt.Println(&s[0], &data[0]) // ?对底层数组起始指针。

====OUTPUT=====
[0 1 100 200] [0 1 2 3 4 5 6 7 8 9]
0xc0001e21e0 0xc000022af0

从输出结果可以看出,append 后的 s 重新分配了底层数组,并复制数据。如果只追加?个值,则不会超过 s.cap 限制,也就不会重新分配

将上面程序改成下面的

data := [...]int{0, 1, 2, 3, 4, 10: 0}
s := data[:2:3]
s = append(s, 100)
fmt.Println(s, data)
fmt.Println(&s[0], &data[0])
s = append(s, 200)  
fmt.Println(s, data) // 重新分配底层数组,与原数组?关。
fmt.Println(&s[0], &data[0]) // ?对底层数组起始指针。

====OUTPUT=====
[0 1 100] [0 1 100 3 4 5 6 7 8 9]
0xc00011e9b0 0xc00011e9b0
[0 1 100 200] [0 1 100 3 4 5 6 7 8 9]
0xc00013dd70 0xc00011e9b0

4.2.2.6 copy

copy 函数可以实现在两个 slice 间复制数据,复制?度以 len?的为准。两个 slice 可指向同?底层数组,允许元素区间重叠。

data := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
s := data[8:]
s2 := data[:5]
copy(s2, s) 
fmt.Println(s2)
fmt.Println(data)

====OUTPUT=====
[8 9 2 3 4]
[8 9 2 3 4 5 6 7 8 9]

4.2.2.7 扩容

当切片的长度超过容量的情况下,切片会进行扩容操作;通常以 2 倍容量重新分配底层数组。在?批量添加数据时,建议?次性分配?够?的空间,以减少内存分配和数据复制开销。或初始化?够?的 len 属性,改?索引号进?操作。及时释放不再使?的 slice 对象,避免持有过期数组,造成 GC ?法回收


结束语

在go语言里,切边是一个应用极为广泛的数据对象;所以在学习golang的过程中,一定要好好地掌握切片的相关知识。

相关推荐

Nginx 响应提速10倍,你需要知道的缓存性能优化——FastCGI调优
Nginx 响应提速10倍,你需要知道的缓存性能优化——FastCGI调优

Nginx缓存优化是帮助大家提升网站性能的重要操作之一,proxy_cache主要用于反向代理时,对后端内容源服务器进行缓存;fastcgi_cache主要用于...

2024-05-20 14:44 gowuye

王者荣耀天魔缭乱和逐梦之音返场活动地址 3月22日开启返场活动
王者荣耀天魔缭乱和逐梦之音返场活动地址 3月22日开启返场活动

王者荣耀官方终于确定了天魔缭乱和逐梦之音的返场活动,这让不少小伙伴乐开了花,返场活动将会在3月22日开启,下面就带来王者荣耀天魔缭乱和逐梦之音返场活动地址!王者...

2024-05-20 14:44 gowuye

常见的嵌入式web服务器有哪些?

嵌入式WEB服务器常见的有:Lighttpd,Shttpd,Thttpd,Boa,Mini_httpd,Appweb,Goahead。Lighttpd地址:http://www.light...

简述几款常见的嵌入式web服务器
简述几款常见的嵌入式web服务器

嵌入式web服务器,是web服务器当中的一种,是基于嵌入式系统而实现的web服务器。指的是在嵌入式系统(通俗点就是单片机系统)上实现的一个web服务器,可以通过...

2024-05-20 14:44 gowuye

教你如何利用fastcgi_cache缓存加速WordPress

在使用nginx缓存之前,必须在nginx里面加载专门的模块,这个模块叫做ngx_cache_purge。添加ngx_cache_purge模块下载ngx_cache_purge模块ngx_cache...

扫描WordPress漏洞

检测已知漏洞WPScan是一款广泛使用的WordPress安全扫描工具,它的一项重要功能是检测已知漏洞。在这篇文章中,我们将深入探讨WPScan如何检测已知漏洞,并结合实际示例,帮助读者更好地理解和应...

消灭 Bug!推荐几个给力的开源 Bug 跟踪工具
消灭 Bug!推荐几个给力的开源 Bug 跟踪工具

在这个充满bug的世界里,最遥远的距离不是生与死,而是你亲手制造的bug就在你眼前,你却怎么都找不到它。因此本文准备了7款优秀的开源bug跟踪系...

2024-05-20 14:43 gowuye

生物信息分析入门全攻略

生物信息学是生命科学研究的重大前沿领域,未来将占据生命科学研究的半壁江山。已经有越来越多的小伙伴投入到生物信息的学习中,但是入门难、深入慢、摸不到方向等都成为持续学习的拦路虎。本文根据生物信息技术大牛...

elkb实践经验,再赠送一套复杂的配置文件
elkb实践经验,再赠送一套复杂的配置文件

原创:小姐姐味道(微信公众号ID:xjjdog),欢迎分享,转载请保留出处。宝剑锋从磨砺出,梅花香自苦寒来。诗人白居易,三月下江南,看到沿路开放的桃花,心潮澎湃...

2024-05-20 14:43 gowuye

超详细从0到1 搭建ELK监控
超详细从0到1 搭建ELK监控

监控分类?Metrics用于记录可聚合的数据。例如,1、队列的当前深度可被定义为一个度量值,在元素入队或出队时被更新;HTTP请求个数可被定义为一个计数器,...

2024-05-20 14:42 gowuye

嵌入式开发 之Web配置页面开发
嵌入式开发 之Web配置页面开发

1.PHP是最好的语言??开发动态页面首选的语言是PHP,村村不能在这里忽悠人,如果你的硬件性能允许切略懂PHP,看到这里就可以退出了。本文面向的受众是Linu...

2024-05-20 14:42 gowuye

Python开发一个网站目录扫描工具用来检测网站是否有漏洞?
Python开发一个网站目录扫描工具用来检测网站是否有漏洞?

开发一个网站目录扫描工具是用来检测网站是否有非法目录请求的一个常见需求之一,我们要通过这个扫描工具来找到通过某个域名可以访问到的网站路径,可能对于有些系统来讲,...

2024-05-20 14:42 gowuye

创建一个类似Youtube的Id——使用PHP/Python/JS/Java/SQL

id通常都是用数字,不巧的是只有10个数字来使用,所以如果你有很多的记录,id往往变得非常冗长。当然对于计算机来说无所谓,但我们更希望id尽可能短。所以我们如何能使id变短?我们可以利用字母让它们附加...

快速云:有助于移动应用安全开发的五条妙计
快速云:有助于移动应用安全开发的五条妙计

许多企业不断地向其开发团队提供培训。但是某些漏洞,如早在十多年前就发现的SQL注入,如今仍广泛存在于各种应用中。因而,安全培训永不过时。在开发移动应用时,开发者...

2024-05-20 14:41 gowuye

洛杉矶国际电影节最佳动画短片奖影片《G’DAY》正式全网上映
洛杉矶国际电影节最佳动画短片奖影片《G’DAY》正式全网上映

7月2日,由M&CSaatchi创作,由深受好评的澳大利亚导演迈克尔·格雷西执导的动画短片《G’day》,正式在全网上映。该影片因其出色的创意赢得了洛...

2024-05-20 14:41 gowuye

取消回复欢迎 发表评论: