内存使用情况:nil interface{} 与 struct{}

我正在尝试了解有关内存使用的更多信息。


对interface{}和struct{}切片进行一些测试,我注意到切片struct{}不分配任何内存,而切片则分配任何内存interface{}。这对我来说没有多大意义,我实际上期望相同的行为(即两者都不分配任何内容)。无论如何,我找不到关于这个特殊案例的任何解释。


有人可以解释一下为什么会发生这种情况吗?


package main


import (

    "runtime"

    "fmt"

)


func main() {

    // Below is an example of using our PrintMemUsage() function

    // Print our starting memory usage (should be around 0mb)

    fmt.Println("Start")

    PrintMemUsage()

    fmt.Println("")


    structContainer := make([]struct{}, 1000000)

    for i := 0; i<1000000; i++ {

    structContainer[i] = struct{}{}

    }


    fmt.Println("With 1kk struct{}")

    PrintMemUsage()

    fmt.Println("")


    nilContainer := make([]interface{}, 1000000)

    for i := 0; i<1000000; i++ {

    nilContainer[i] = nil

    }


    fmt.Println("With 1kk nil interface{}")

    PrintMemUsage()

    fmt.Println("")

}


// PrintMemUsage outputs the current, total and OS memory being used. As well as the number 

// of garage collection cycles completed.

func PrintMemUsage() {

        var m runtime.MemStats

        runtime.ReadMemStats(&m)

        // For info on each, see: https://golang.org/pkg/runtime/#MemStats

        fmt.Printf("Alloc = %v KiB", bToMb(m.Alloc))

        fmt.Printf("\tTotalAlloc = %v KiB", bToMb(m.TotalAlloc))

        fmt.Printf("\tSys = %v KiB", bToMb(m.Sys))

        fmt.Printf("\tNumGC = %v\n", m.NumGC)

}


func bToMb(b uint64) uint64 {

    return b / 1024

}


HUH函数
浏览 84回答 2
2回答

梦里花落0921

这是因为空结构不包含任何值。这对于数组或切片来说不是很有用。但它对于地图很有用。没有价值的地图就像一套。您可以插入密钥并测试它们是否存在。正如您所发现的,缺乏价值可以节省空间。

慕无忌1623718

类型变量interface{}可以保存任何值。例如,它可以保存整数8,可以保存string值"hi",可以保存结构值image.Point{X: 1, Y: 2}以及几乎所有其他内容。如果您分配一个具有interface{}其元素类型的切片,则必须分配内存,以便您可以在其元素中存储任何值。当使用make()分配它时,它的所有元素都将获得元素类型的零值(这是nil针对interface{}),但仍然需要分配内存,否则以后将无法设置元素。另一方面,空结构struct{}没有字段,它不能保存任何值(除了struct{})。当您分配一个具有struct{}其元素类型的切片时,不需要分配内存,因为您将无法在其中存储任何需要内存的内容。所以不为这种类型分配内存是一个简单而聪明的优化。
打开App,查看更多内容
随时随地看视频慕课网APP