教程 > Go 教程 > Go 高级 阅读:389

Go 语言切片内存优化

Go 语言将切片作为参数传递给函数 一章中,我们介绍了其实切片是一个对数组的结构体的表示。在Go语言中,其底层表示如下所示

type slice struct {  
    Length        int
    Capacity      int
    ZerothElement *byte
}

切片保存对底层数组的引用。但是这里就会有一个问题,只要切片在内存中,数组就不能被垃圾回收。

当涉及到内存管理时,这可能会引起关注。假设我们有一个非常大的数组,但是我们只是需要处理其中的一小部分。然后,我们从该数组创建一个切片并开始处理这个切片。这里要注意的重要一点是数组仍然在内存中,因为切片引用了它。

Go 切片引用部分数组
Go 切片引用部分数组

我们可以看到,底层的数组有 n 个元素。但是我们只需要其中的四个元素来处理。如果创建的切片一直在内存中,那这个具有n个元素的数组也一直在内存中不会被释放。

解决此问题的一种方法是使用复制功能,语法如下

func copy(dst, src []T) int 

使用 copy() 函数来生成切片的副本。这样我们就可以使用新的切片,并且可以对原始数组进行垃圾回收。

Go 切片拷贝功能copy
Go 切片拷贝功能copy

下面我们看一个示例

package main

import (  
    "fmt"
)

func countries() []string {  
    countries := []string{"USA", "Singapore", "Germany", "India", "Australia"}
    neededCountries := countries[:len(countries)-2]
    countriesCpy := make([]string, len(neededCountries))
    copy(countriesCpy, neededCountries) //将neededCountries 拷贝到 countriesCpy
    return countriesCpy
}
func main() {  
    countriesNeeded := countries()
    fmt.Println(countriesNeeded)
}

运行示例

上述代码执行结果如下

[USA Singapore Germany]

上面程序的 neededCountries := countries[:len(countries)-2] 创建了一个切片,该切片除了countries的最后 2 个元素。然后创建了一个新的切片 countriesCpy。接下来将neededCountries拷贝到countriesCpy并从函数返回countriesCpy。现在countries 数组可以被当作垃圾回收,因为neededCountries不再被引用。

查看笔记

扫码一下
查看教程更方便