Глядя на профилировщик, похоже, что это действительно утечка памяти (go1.11.5 darwin / amd64)
Давайте посмотрим на профилировщик.
Я нашел онлайн-пример для отладки памяти . Приспосабливаясь к моему примеру, я сделал это:
package main
import (
"fmt"
"os"
"runtime"
"runtime/debug"
"runtime/pprof"
)
const aLot = 5000000
func getInteriorPointer() *int {
type bigStruct struct {
someBigThing [aLot]int
smallThing int
}
b := bigStruct{smallThing: 3}
return &b.smallThing
}
func main() {
p := getInteriorPointer()
runtime.GC()
debug.FreeOSMemory()
fmem, _ := os.Create("prof.prof")
pprof.WriteHeapProfile(fmem)
// keep using p in the rest of the app,
// never using someBigThing from the struct
fmt.Println(*p)
}
Теперь я бегу go tool pprof prof.prof
и list main
ROUTINE ======================== main.getInteriorPointer in /Users/karel/exp/exp.go
38.15MB 38.15MB (flat, cum) 100% of Total
. . 13:func getInteriorPointer() *int {
. . 14: type bigStruct struct {
. . 15: someBigThing [aLot]int
. . 16: smallThing int
. . 17: }
38.15MB 38.15MB 18: b := bigStruct{smallThing: 3}
. . 19: return &b.smallThing
. . 20:}
. . 21:
. . 22:func main() {
. . 23: p := getInteriorPointer()
ROUTINE ======================== main.main in /Users/karel/exp/exp.go
0 38.15MB (flat, cum) 100% of Total
. . 18: b := bigStruct{smallThing: 3}
. . 19: return &b.smallThing
. . 20:}
. . 21:
. . 22:func main() {
. 38.15MB 23: p := getInteriorPointer()
. . 24: runtime.GC()
. . 25: debug.FreeOSMemory()
. . 26: fmem, _ := os.Create("prof.prof")
. . 27: pprof.WriteHeapProfile(fmem)
. . 28:
Кажется, сборщик мусора действительно не удаляет ненужный объект из памяти. Если Я правильно понимаю формат. (Возможно, нет, поскольку документации почти нет.)