内存使用:nil interface{} vs struct{}

DrK*_*Key 3 memory-management go

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

使用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
}
Run Code Online (Sandbox Code Playgroud)

游乐场链接

icz*_*cza 6

类型变量interface{}可以保存任何值。例如,它可以保存整数8,可以保存string"hi",可以保存结构值image.Point{X: 1, Y: 2}以及几乎所有其他内容。

如果分配具有interface{}元素类型的切片,则必须分配内存,以便您可以在其元素中存储任何值。当make()用于分配它时,它的所有元素都将获得元素类型的零值(nil用于interface{}),但仍然必须分配内存,否则您以后无法设置元素。

另一方面,空结构struct{}没有字段,它不能保存任何值(除了struct{})。当您分配具有struct{}元素类型的切片时,不需要分配内存,因为您将无法在其中存储任何需要内存的内容。所以不为这种类型分配内存是一个简单而聪明的优化。