Go数组&切片使用

uuid · · 605 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

## 声明 数组: ```go var array [size] string ``` 切片: ```go var slice [] string ``` **差异**:数组的声明需要指定“**size**”,如果不指定就是为切片(slice) ## 初始化 **数组:** ```go var array1 = [3] string{"one", "two", "three"} var array2 = [...] string{"one", "two", "three"} array3 := [...] string{"one", "two", "three"} // 推荐:无需通过var声明 ``` **切片:** ```go var slice [] string slice = make([]string, 5, 5) // 指定长度为5,容量为5的切片 slice = make([]string,5) // 指定长度为5,容量为5的切片 slice2 := [] string{"one", "two", "three"} // 推荐:无需通过var声明 ``` 注:大部分情况下如果不知道切片长度,只要声明,无需初始化,单需要往切片增加数据是,通过append添加(声明的切面默认值是nil,但是append并不会异常) ## 常用操作 ### 读取 **数组** 数组一般是在for循环中通过索引,或是range 直接读取: ```go aa := [5] string{} for i, a := range aa { // aa的副本 fmt.Println("i= ", i, ", s=", a) } for i:=0; i< len(aa); i++ { fmt.Println("i= ", i, ", s=", aa[i]) } ``` 注意: range 的是数组的副本,也是就是说会把aa拷贝一份,并且读取出来的项也是对应的副本,所以对项的修改是不会影响原有的数组,当aa比较大的时候会影响性能,所以可以采用读取数组指针的方式来优化: ```go for i, a := range &aa { // 这里拷贝的会是aa的指针 fmt.Println("i= ", i, ", s=", a) } ``` **切片** 切片的读取和数组类似一般是在for循环中通过索引,或是range 直接读取: ```go aa := [] string{“hello”, "world"} for i, a := range aa { // aa副本,但是由于切片时特殊的结构体,并不会保存整个数组,而是数据组第一个元素的地址,所以就算副本对性能也不会有太大影响 fmt.Println("i= ", i, ", s=", a) } for i:=0; i< len(aa); i++ { fmt.Println("i= ", i, ", s=", aa[i]) } ``` 注意: 切片和数组存在一些差异,切片range的时候拷贝的是slice的数据,底层还是共享数组,所以修改的时候回会影响原来slice ### 添加 数组: 一个数组中的元素个数总是恒定的,我们无法向其中添加元素,也无法从其中删除元素。但是元素可以通过索引修改值 ```go aa := [5] string{} aa[0] = "张三" ``` 切片: 切片的底层实际上也是关联一个数组,所以如果新增元素超过数组的容量,内部会重新开辟一个数组大于(小于1024翻倍,大于增加25%)当前的数组 **头部插入** ```go aa := [] string{"张三", "李四"} result := append([]string{"王五"}, aa...) // result = {"王五", "张三", "李四"} ``` **尾部追加** ```go aa := [] string{"张三", "李四"} result := append(aa, "王五", "张飞") // 可以追加多个,result = { "张三", "李四", "王五", "张飞"} ``` ### **删除** 删除第i个元素 ```go // 第一种方法(保持剩余元素的次序): s = append(s[:i], s[i+1:]...) // 第二种方法(保持剩余元素的次序): s = s[:i + copy(s[i:], s[i+1:])] // 上面两种方法都需要复制len(s)-i-1个元素。 // 第三种方法(不保持剩余元素的次序): s[i] = s[len(s)-1] s = s[:len(s)-1] ``` 条件删除:keep判断条件,需要保留的返回true ```go func filter(data [] *T, keep func(item *T) bool, clear bool) [] *T{ result:=data[:0] // 复用data内存,无需另外开辟。(注:会修改原切片共享数组内容) for _, d := range data { if keep(d) { result = append(result, d) } } if clear { // 避免暂时性的内存泄露。 temp := data[len(result):] for i := range temp { temp[i] = nil // t0是类型T的零值 } } return result } ``` ### 拷贝 拷贝b切片 **方法1** ``` var b [] T if a!=nil{ b = make([]T, len(a)) copy(b, a) } ``` **方法2** ```go var b [] T if a!=nil{ b = append([]T(nil), a...) } ``` **方法3(最简洁)** ```go b = append(a[:0:0], a...) ``` 这里就利用了当a为nil的是时候,a[:0:0]并不会报错,仍然会是nil且a[:0:0] == nil为true 我的博客:[Go数组&切片使用 | 艺术码农的小栈](https://itart.cn/blogs/2021/practice/go-array-slice-demo.html)

有疑问加站长微信联系(非本文作者))

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

605 次点击  ∙  1 赞  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传