网上相关内容都是说:
"由于底层都是数组,如果截图长slice的一段,其实相当于引用了底层数组中的一小段。只要还有引用,golang的gc就不能回收数组。这种情况导致未使用的数组空间,未及时回收。"
即go切片做了reslice, 底层数组只要有引用, 是不会被回收的
但是我做了简单的测试, 发现不是这样呢? 下面的代码跑出来, 在调用runtime.GC之后内存明显被回收了。请大家帮忙看看问题在哪里
```golang
package main
import (
"fmt"
_ "github.com/mkevac/debugcharts"
_ "net/http/pprof"
"runtime"
)
type pslice *[]int
func makeArr() []pslice {
arr := make([]pslice, 800000)
return arr
}
func printMem() {
var rtm runtime.MemStats
runtime.ReadMemStats(&rtm)
fmt.Printf("%f MB\n", float64(rtm.Alloc)/1024./1024.)
}
func main() {
arr := makeArr()
for i := 0; i < len(arr); i++ {
slice:=make([]int,100)
arr[i] = &slice
}
arr=arr[:5]
printMem()//716.924133 MB
runtime.GC()
printMem()//8.912193 MB
}
```
```go
package main
import (
"fmt"
_ "net/http/pprof"
"runtime"
)
type pslice *[]int
func makeArr() []pslice {
arr := make([]pslice, 800000)
return arr
}
func printMem() {
var rtm runtime.MemStats
runtime.ReadMemStats(&rtm)
fmt.Printf("%f MB\n", float64(rtm.Alloc)/1024./1024.)
}
func main() {
arr := makeArr()
for i := 0; i < len(arr); i++ {
slice := make([]int, 100)
arr[i] = &slice
}
arr = arr[:5]
printMem() //716.924133 MB
runtime.GC()
fmt.Println(len(arr))//注意这行
printMem() //8.912193 MB
}
```
结果:
```
708.285545 MB
5
708.290962 MB
```
#5
更多评论
谢谢回复, 但是我没太看懂你说的呢?
我想知道一个切片做了reslice操作, 如arr=arr[:1]之后, 底层数组多出的部分会被垃圾回收吗?
我觉得理论上不应该垃圾回收, 但是上面代码, 我在堆上面分配了一个长度为800000的切片, 在此切片基础上切片, 之后调用printMem打印当前内存分配
在垃圾回收前后明显内存降低了啊, 这不是被回收了吗?比较疑惑
#2