go语言的切片研究

简介: go语言的切片研究

切片slice

Go 语言切片是对数组的抽象。

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

声明切片

package main
import "fmt"
func main() {
   //1:direct declare variable
   var s1  \[\]int
   //s1 = \[\]int{}
   fmt.Printf("s1: %v,len: %v,cap: %v \\n",s1,len(s1),cap(s1))
   //2:assignment variable
   s2  := \[\]int{1,2,3}
   fmt.Printf("s2: %v,len: %v,cap: %v \\n",s2,len(s2),cap(s2))
   //3:make slice
   s3 :=make(\[\]int,0)
   fmt.Printf("s3 %v,len: %v,cap: %v \\n",s3,len(s3),cap(s3))
   //3:make slice and assignment slice length
   s4 :=make(\[\]int,0,10)
   fmt.Printf("s4: %v,len: %v,cap: %v \\n",s4,len(s4),cap(s4))
   //4:slice by array
   arr := \[5\]int{1,2,3,4,5}
   s5 := arr\[:\]
   fmt.Printf("s5: %v,len: %v,cap: %v \\n",s5,len(s5),cap(s5))
   s6 := arr\[1:len(arr)-1\]
   fmt.Printf("s6: %v,len: %v,cap: %v \\n",s6,len(s6),cap(s6))
   //5:slice by slice
   s7 := \[\]int{1,2,3,4,5,6,7,8,9,10}
   fmt.Printf("s7: %v,len: %v,cap: %v \\n",s7,len(s7),cap(s7))
   s8 := s7\[1:len(arr)-1\]
   fmt.Printf("s8: %v,len: %v,cap: %v \\n",s8,len(s8),cap(s8))
   //\[x:y:z\]  x:start index y:end index z:slice cap=z-x
   s9 := s7\[6:10:10\]
   fmt.Printf("s9: %v,len: %v,cap: %v \\n",s9,len(s9),cap(s9))
}

切片cap,len

cap


切片容量,在追加切片时,可能会使得切片容量变大

len

切片长度,表示切片数组的长度

package main
import "fmt"
func main() {
   var s1  \[\]int
   fmt.Printf("s1: %v,len: %v,cap: %v \\n",s1,len(s1),cap(s1))
   s1 = \[\]int{1,2,3}
   fmt.Printf("s1: %v,len: %v,cap: %v \\n",s1,len(s1),cap(s1))
   var arr =\[\]int{1,2,3,4,5,6,7,8,9,10}
   s2 := arr\[0:5\]
   fmt.Printf("s2: %v,len: %v,cap: %v \\n",s2,len(s2),cap(s2))
}

输出:

image.png

可以看到,在数组中获取切片后,cap=10,len=5

切片的cap永远是大于等于len的

空nil切片

切片未初始化之前,切片等于nil,len和cap都为0

操作切片

append 切片追加数据

package main
import (
   "fmt"
)
func main() {
   var s1 = make(\[\]int,0,10)
   fmt.Printf("s1: %v,len: %v,cap: %v \\n",s1,len(s1),cap(s1))
   s1 = append(s1,1,2,3,4 )
   fmt.Printf("s1: %v,len: %v,cap: %v \\n",s1,len(s1),cap(s1))
}

当追加的数据超出cap容量时,将会触发切片重新分配底层数组,即时原数组并未被填满

重新分配底层数组时,一般以原有cap进行二倍扩容分配

package main
import (
   "fmt"
)
func main() {
   var s1 = make(\[\]int,0,4)
   fmt.Printf("s1: %v,len: %v,cap: %v \\n",s1,len(s1),cap(s1))
   s1 = append(s1,1,2,3,4)
   fmt.Printf("1 s1 pointer: %p \\n",s1)
   fmt.Printf("s1: %v,len: %v,cap: %v \\n",s1,len(s1),cap(s1))
   fmt.Printf("2 s1 pointer: %p \\n",s1)
   s1 = append(s1,5,6)
   fmt.Printf("s1: %v,len: %v,cap: %v \\n",s1,len(s1),cap(s1))
   fmt.Printf("3 s1 pointer: %p \\n",s1)
}

注意:由于每次超出时都会重新分配数组,在开发时应该避免重新分配,一次性定义好切片的容量

copy

copy函数可以将一个切片的元素复制到另一个切片,复制的长度由最小的切片长度为准:

package main
import (
   "fmt"
)
func main() {
   var s1 = make(\[\]int, 0, 4)
   var s2 = make(\[\]int, 0, 10)
   s1 = append(s1, 9)
   s2 = append(s2, 1, 2, 3, 4, 5, 6)
   copy(s2,s1)
   fmt.Printf("s1: %v,len: %v,cap: %v \\n", s1, len(s1), cap(s1))
   fmt.Printf("s2: %v,len: %v,cap: %v \\n", s2, len(s2), cap(s2))
}

输出:

s1: \[9\],len: 1,cap: 4 
s2: \[9 2 3 4 5 6\],len: 6,cap: 10

当s1复制到s2时,s1的元素将完全复制到s2中(如果s2容量比s1长度小,则会忽略s1超出的部分)

切片copy自身

当切片 通过[:x]方式创建新切片时,将直接使用原有切片的地址,同时如果新切片发生了更改,原有切片也将发生更改:

package main
import (
   "fmt"
)
func main() {
   s1 :=\[\]int{1,2,3,4,5,6,7,8,9}
   s2 :=s1\[8:\]
   s3 :=s1\[:8\]
   fmt.Printf("s1 pointer:%p \\n", s1)
   fmt.Printf("s2 pointer:%p \\n", s2)
   fmt.Printf("s3 pointer:%p \\n", s3)
   //s2 pointer == s3 pointer
   copy(s3,s2)
   fmt.Printf("s3: %v,len: %v,cap: %v \\n", s3, len(s3), cap(s3))
   fmt.Printf("s1: %v,len: %v,cap: %v \\n", s1, len(s1), cap(s1))
}

输出:

s1 pointer:0xc00001e0a0 
s2 pointer:0xc00001e0e0 
s3 pointer:0xc00001e0a0 
s3: \[9 2 3 4 5 6 7 8\],len: 8,cap: 9 
s1: \[9 2 3 4 5 6 7 8 9\],len: 9,cap: 9

切片遍历

可直接通过range遍历:

package main
import (
   "fmt"
)
func main() {
   s1 := \[\]int{1, 2, 3, 4, 5, 6, 7, 8, 9}
   fmt.Printf("s1: %v,len: %v,cap: %v \\n", s1, len(s1), cap(s1))
   for key, value := range s1 {
      fmt.Printf("key:%v,value:%v \\n",key,value)
   }
}
目录
打赏
0
0
0
0
7
分享
相关文章
监控局域网其他电脑:Go 语言迪杰斯特拉算法的高效应用
在信息化时代,监控局域网成为网络管理与安全防护的关键需求。本文探讨了迪杰斯特拉(Dijkstra)算法在监控局域网中的应用,通过计算最短路径优化数据传输和故障检测。文中提供了使用Go语言实现的代码例程,展示了如何高效地进行网络监控,确保局域网的稳定运行和数据安全。迪杰斯特拉算法能减少传输延迟和带宽消耗,及时发现并处理网络故障,适用于复杂网络环境下的管理和维护。
揭秘 Go 语言中空结构体的强大用法
Go 语言中的空结构体 `struct{}` 不包含任何字段,不占用内存空间。它在实际编程中有多种典型用法:1) 结合 map 实现集合(set)类型;2) 与 channel 搭配用于信号通知;3) 申请超大容量的 Slice 和 Array 以节省内存;4) 作为接口实现时明确表示不关注值。此外,需要注意的是,空结构体作为字段时可能会因内存对齐原因占用额外空间。建议将空结构体放在外层结构体的第一个字段以优化内存使用。
Go 切片导致 rand.Shuffle 产生重复数据的原因与解决方案
在 Go 语言开发中,使用切片时由于其底层数据共享特性,可能会引发意想不到的 Bug。本文分析了 `rand.Shuffle` 后切片数据重复的问题,指出原因在于切片是引用类型,直接赋值会导致底层数组共享,进而影响原始数据。解决方案是使用 `append` 进行数据拷贝,确保独立副本,避免 `rand.Shuffle` 影响原始数据。总结强调了切片作为引用类型的特性及正确处理方法,确保代码稳定性和正确性。
120 82
|
1月前
|
Go 语言入门指南:切片
Golang中的切片(Slice)是基于数组的动态序列,支持变长操作。它由指针、长度和容量三部分组成,底层引用一个连续的数组片段。切片提供灵活的增减元素功能,语法形式为`[]T`,其中T为元素类型。相比固定长度的数组,切片更常用,允许动态调整大小,并且多个切片可以共享同一底层数组。通过内置的`make`函数可创建指定长度和容量的切片。需要注意的是,切片不能直接比较,只能与`nil`比较,且空切片的长度为0。
Go 语言入门指南:切片
|
1月前
|
公司局域网管理系统里的 Go 语言 Bloom Filter 算法,太值得深挖了
本文探讨了如何利用 Go 语言中的 Bloom Filter 算法提升公司局域网管理系统的性能。Bloom Filter 是一种高效的空间节省型数据结构,适用于快速判断元素是否存在于集合中。文中通过具体代码示例展示了如何在 Go 中实现 Bloom Filter,并应用于局域网的 IP 访问控制,显著提高系统响应速度和安全性。随着网络规模扩大和技术进步,持续优化算法和结合其他安全技术将是企业维持网络竞争力的关键。
52 2
公司局域网管理系统里的 Go 语言 Bloom Filter 算法,太值得深挖了
eino — 基于go语言的大模型应用开发框架(二)
本文介绍了如何使用Eino框架实现一个基本的LLM(大语言模型)应用。Eino中的`ChatModel`接口提供了与不同大模型服务(如OpenAI、Ollama等)交互的统一方式,支持生成完整响应、流式响应和绑定工具等功能。`Generate`方法用于生成完整的模型响应,`Stream`方法以流式方式返回结果,`BindTools`方法为模型绑定工具。此外,还介绍了通过`Option`模式配置模型参数及模板功能,支持基于前端和用户自定义的角色及Prompt。目前主要聚焦于`ChatModel`的`Generate`方法,后续将继续深入学习。
310 7
企业监控软件中 Go 语言哈希表算法的应用研究与分析
在数字化时代,企业监控软件对企业的稳定运营至关重要。哈希表(散列表)作为高效的数据结构,广泛应用于企业监控中,如设备状态管理、数据分类和缓存机制。Go 语言中的 map 实现了哈希表,能快速处理海量监控数据,确保实时准确反映设备状态,提升系统性能,助力企业实现智能化管理。
36 3
eino — 基于go语言的大模型应用开发框架(一)
Eino 是一个受开源社区优秀LLM应用开发框架(如LangChain和LlamaIndex)启发的Go语言框架,强调简洁性、可扩展性和可靠性。它提供了易于复用的组件、强大的编排框架、简洁明了的API、最佳实践集合及实用的DevOps工具,支持快速构建和部署LLM应用。Eino不仅兼容多种模型库(如OpenAI、Ollama、Ark),还提供详细的官方文档和活跃的社区支持,便于开发者上手使用。
253 8
Go 语言中的 Sync.Map 详解:并发安全的 Map 实现
`sync.Map` 是 Go 语言中用于并发安全操作的 Map 实现,适用于读多写少的场景。它通过两个底层 Map(`read` 和 `dirty`)实现读写分离,提供高效的读性能。主要方法包括 `Store`、`Load`、`Delete` 等。在大量写入时性能可能下降,需谨慎选择使用场景。
Go语言实战:错误处理和panic_recover之自定义错误类型
本文深入探讨了Go语言中的错误处理和panic/recover机制,涵盖错误处理的基本概念、自定义错误类型的定义、panic和recover的工作原理及应用场景。通过具体代码示例介绍了如何定义自定义错误类型、检查和处理错误值,并使用panic和recover处理运行时错误。文章还讨论了错误处理在实际开发中的应用,如网络编程、文件操作和并发编程,并推荐了一些学习资源。最后展望了未来Go语言在错误处理方面的优化方向。
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等