这篇文章主要介绍了golang切片内存应用详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

在 Go 语言中切片是使用非常频繁的一种聚合类型,它代表变长的序列,底层引用一个数组对象。一个切片由三个部分构成:指针、长度和容量。指针指向该切片自己第一个元素对应的底层数组元素的内存地址。

切片的类型声明如下:

type slice struct {
 array unsafe.Pointer
 len  int
 cap  int
}

多个切片之间可以共享底层数组的数据,并且引用的数组区间可能重叠。利用切片 的这个特性我们可以在原有内存空间中对切片进行反转、筛选和去重等操作,这样就不用声明一个指向新内存的切片来存储结果,从而节省了内存空间以及扩展底层数组的消耗,这在切片长度足够大时效果就会非常显著。

下面这些例子都是在切片底层数组的内存空间上进行的操作,需要注意的是这些操作在底层数组上生成新切片的同时也会更改底层数组。

删除指定位置的元素

下面的函数从原切片中删除索引位置i上的元素

func remove(slice []int, i int) []int {
  copy(slice[i:], slice[i+1:])
  return slice[:len(slice)-1]
}

func main() {
  s := []int{5, 6, 7, 8, 9}
  fmt.Println(remove(s, 2)) // "[5 6 8 9]"
}

内置的copy函数可以方便地将一个切片复制另一个相同类型的切片上。

筛选元素

下面的函数从输入的源切片中筛选出条件的切片元素,返回一个条件的元素组成的新切片。

type funcType func(T) bool //代表筛选逻辑函数,可以按需实现

func filter(a []T, f funcType) []T {
  b := a[:0]
  for _, x := range a {
   if f(x) { 
   b = append(b, x)
   }
  }
  return b
}

反转切片

func reverse(a []T) []T {
  for i := len(a)/2-1; i >= 0; i-- {
    opp := len(a)-1-i
   a[i], a[opp] = a[opp], a[i]
 }
 
 return a
}

分组切片

下面的函数接收一个[]int 类型的源切片actions, 返回一个按指定长度分组的嵌套切片(解释起来好难,用过PHP 的同学可以理解为 Go 版本的array_chunk 函数,没用过的看下面例子)。假设切面值为:[]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9},设置分组中元素长度batchSize为3,函数调用后返回的分组后的切片为[[0 1 2] [3 4 5] [6 7 8] [9]]

func chunk(actions []int, batchSize int) []int {
 var batches [][]int

 for batchSize < len(actions) {
   actions, batches = actions[batchSize:], append(batches, actions[0:batchSize:batchSize])
 }
 batches = append(batches, actions)
 
  return batches
}

func main() {
 actions := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
 batchSize := 3
  chunks = chunk(actions, batchSize)
  //chunks 为[[0 1 2] [3 4 5] [6 7 8] [9]]
}

这里顺便说一下,完整的切片表达式形式如下:

input[low:high:max]

最后一个 max 的作用是,生成的切片的cap(容量)为max - low。

原地去重(只针对可比较的切片类型)

import "sort"

func main() {
 in := []int{3,2,1,4,3,2,1,4,1} // any item can be sorted
 sort.Ints(in)
 j := 0
 for i := 1; i < len(in); i++ {
    if in[j] == in[i] {
      continue
 }
 j++

 in[j] = in[i]
 }
 result := in[:j+1]
 fmt.Println(result) // [1 2 3 4] 
}

文章中部分例子来自golang 官方的 GitHub 的 wiki ,在这个 wiki 里介绍了很多的切片使用,了解更多可以访问golang 的 GitHub Wiki https://github.com/golang/go/wiki/SliceTricks#filtering-without-allocating

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持爱安网。

最新资讯
专挑处女果蝇?实验人员:为了科研!

专挑处女果蝇?实验人员

提到果蝇,很多人立马想到烂水果旁边那堆烦人的小蝇子,轰
银河系外的行星,可能首次被人类找到了

银河系外的行星,可能首

在2800万光年之外,我们首次找到了银河系外行星?一项最新
苹果暂免在Facebook上运行付费在线活动企业30%抽成至2020年底

苹果暂免在Facebook上

Facebook方面表示,在其iOS应用上运行付费在线活动的企
华为东莞基地着火现场:建筑位于团泊洼实验室 园区仍被封锁

华为东莞基地着火现场

此次失火的建筑系华为团泊洼实验室园区内的G2栋建筑,据
高瓴资本黄立明:平台企业无长久垄断,腾讯、阿里之外仍有大空间

高瓴资本黄立明:平台企

平台必须有原生的价值,这样的平台才会有自己“滚雪球”
亏损、还债!罗永浩“真还传”还得演,“直播电商最多占一半”

亏损、还债!罗永浩“真

9月23日晚,自称“脱口秀前辈”的罗永浩在《脱口秀大会
最新文章
GoLang 逃逸分析的机制详解

GoLang 逃逸分析的机

这篇文章主要介绍了GoLang-逃逸分析的机制详解,文中通
golang 生成二维码海报的实现代码

golang 生成二维码海

这篇文章主要介绍了golang 生成二维码海报的实现代码,
golang语言实现的文件上传与文件下载功能示例

golang语言实现的文件

这篇文章主要介绍了golang语言实现的文件上传与文件下
Golang 实现插入排序的方法示例(2种)

Golang 实现插入排序

这篇文章主要介绍了Golang 实现插入排序的方法示例,文
图文详解go语言反射实现原理

图文详解go语言反射实

这篇文章主要介绍了图文详解go语言反射实现原理,本文
Golang中的Slice与数组及区别详解

Golang中的Slice与数

数组是一种具有固定长度的基本数据结构,在golang中与C