前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >golang切片内存应用技巧

golang切片内存应用技巧

作者头像
KevinYan
发布2019-12-16 16:07:26
1.1K0
发布2019-12-16 16:07:26
举报
文章被收录于专栏:网管叨bi叨

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

切片的类型声明如下:

代码语言:javascript
复制
type slice struct {
  array unsafe.Pointer
  len   int
  cap   int
}

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

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

删除指定位置的元素

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

代码语言:javascript
复制
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函数可以方便地将一个切片复制另一个相同类型的切片上。

筛选元素

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

代码语言:javascript
复制
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
}

反转切片

代码语言:javascript
复制
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,函数调用后返回的分组后的切片为 [[012][345][678][9]]

代码语言:javascript
复制
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]]
}

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

代码语言:javascript
复制
input[low:high:max]

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

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

代码语言:javascript
复制
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

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-12-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 网管叨bi叨 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 删除指定位置的元素
  • 筛选元素
  • 反转切片
  • 分组切片
  • 原地去重(只针对可比较的切片类型)
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档