我对GoLang的垃圾收集器有些困惑。
考虑以下代码,在其中我为T型实现阅读器接口。
master_df = pd.DataFrame({
'col1': ['M', 'F', 'F', 'M'],
'col2': [0, 1, 2, 3],
'col3': ['X', 'Z', 'Z', 'X'],
'col4': [2021, 2022, 2023, 2024],
'col5': [.632, .232, .37, .5005]
})
其中的阅读器函数中,我将使用master_df
将数据转换为MyDataType,该数据将指向使用反射模块创建的切片(这比较复杂,但出于示例的考虑,这应该足够了)< / p>
DataFrame
如果我要以其他功能读取数据
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))
}
现在我很困惑,如果可能的话,GC将在退出unsafe.Pointer
函数之后从文件中释放已加载的数据。否则将释放func (t *T) readFileData(data []byte, idx int, ...) unsafe.Pointer {
...
return unsafe.Pointer(&reflect.SliceHeader{Data : uintptr(unsafe.Pointer(&data[idx])), ...})
}
之后释放数据。
答案 0 :(得分:1)
要了解GC可能对您的变量执行的操作,首先您需要知道Go如何以及在何处分配变量。这是有关escape analysis的很好的读物,这是Go编译器如何确定在堆栈或堆之间分配内存的位置。
长话短说,只有当Go程序未引用GC时,GC才会释放内存。
在您的示例中,data, _ := ioutil.ReadFile(filename)
对加载数据的引用最终传递给t.Data = *(*[]*MyDataType) (t.readFileData(p))
。因此,只要也引用了(t *T)
结构,就将引用它们。据我从您的代码中看到的那样,加载的数据将与(t *T)
一起进行垃圾收集。
答案 1 :(得分:-2)
根据reflect docs,我必须保留指向data *[]byte
的单独指针,以避免垃圾回收。因此,解决方案是将referencePtr
添加到
type T struct {
header Header
data []*MyDataType
referencePtr *[]byte
}
它将指向Read函数中的我的数据
func (t *T) Read(p []byte) (int, error) {
t.referencePtr = &p
t.Header = *(*Header) (t.readFileHeader(p))
t.Data = *(*[]*MyDataType) (t.readFileData(p))
}
还是这是不必要的?