请教一下,从硬盘读取文件,把里面的内容Unmarshal到struct里,然后内存就不释放了。

我的app启动时,要从硬盘读取几个json文件,Unmarshal一下。

最开始的时候,我写了一个函数如下:

func OpenJson(filePath string, pointToObj interface{}) error {
    b, err := ioutil.ReadFile(filePath)
    if err != nil {
        return err
    }
    return json.Unmarshal(b, pointToObj)
}

但是之后内存就一直不释放了,app启动后内存占用大约一直在385M左右。

然后我改写了一下:

var b []byte
func OpenJson(filePath string, pointToObj interface{})
    var err error
    b, err = ioutil.ReadFile(filePath)
    if err != nil {
        return err
    }
    err = json.Unmarshal(b, pointToObj)
    b = []byte("")
    return err
}

app启动后仍然占用385M左右的内存,但是过了一会儿,内存就释放了,内存占用大约在105M左右。

请教一下,第一次的写法,是不是就不会释放内存了?第二种写法的话,有没有什么最优的做法?

共 3 个回复


jimmykuu

这两种写法当垃圾回收的时候是可以把内存回收的,但是由于都一次性写入到 b 里面,如果文件很大,对内存占用是很大的。

更优雅的写法是通过接口:

func OpenJson(filePath string, pointToObj interface{}) error {
    file, err := os.Open(filePath)
    if err != nil {
        return err
    }
    defer file.Close()

    dec := json.NewDecoder(file)
    err = dec.Decode(&pointToObj)
    return err
}
# 0

leedstyh

@jimmykuu 我试了下,似乎接口的方式占用的内存没有减少。然后我搜索了下,发现这个答案说:json.Decoder也是先把json的值读到内存里的。

# 1

yufeng

你用bytes.Buffer 读json字符串,然后json.Decoder 内存占用也差不多,你可以试试

# 2