I'm a little bit confused with GoLang's garbage collector.
Consider this following code, where I implement reader interface for my type T.
type T struct {
header Header
data []*MyDataType
}
func (t *T) Read(p []byte) (int, error) {
t.Header = *(*Header) (t.readFileHeader(p))
t.Data = *(*[]*MyDataType) (t.readFileData(p))
}
wherein the reader functions I will cast the data to MyDataType using the unsafe.Pointer
which will point to slice created with the reflect module (this is more complicated, but for the sake of the example this should be enough)
func (t *T) readFileData(data []byte, idx int, ...) unsafe.Pointer {
...
return unsafe.Pointer(&reflect.SliceHeader{Data : uintptr(unsafe.Pointer(&data[idx])), ...})
}
and If I am gonna read the data in different function
func (d *Dummy) foo() {
data, _ := ioutil.ReadFile(filename)
d.t.Read(data) <---will GC free data?
}
Now I'm confused if it is possible, that the GC will free loaded data from file after exiting the foo
function. Or the data will be freed after the d.t
is freed.
According to the reflect docs, I've to keep a separate pointer to
data *[]byte
, to avoid garbage collection. So the solution is to add areferencePtr
towhich will point to my data inside the Read function
or is this unnecessary?
To understand what GC might do to your variables, first you need to know how and where Go allocates them. Here is a good reading about escape analysis, that is how Go compiler decides where allocate memory, between stack or heap.
Long story short, GC will free memory only if it is not referenced by your Go program.
In your example, the reference to loaded data by
data, _ := ioutil.ReadFile(filename)
is passed tot.Data = *(*[]*MyDataType) (t.readFileData(p))
ultimately. Therefore, they will be referenced as long as(t *T)
struct is referenced as well. As far as I can see from your code, the loaded data will be garbage-collected along with(t *T)
.