如何在内存中分配Go类型方法集?

时间:2015-07-14 03:26:23

标签: go

C ++避免了每次创建实例时为类方法分配内存。我的直觉是假设Go也减轻了这种重复。只是为了确认,Go是否只存储一次自定义结构的方法集?

type Custom struct {
    value string
}

func (c Custom) TurnItUp() {
    c.value = "up"
}

func (c Custom) TurnItDown() {
    c.value = "down"
}

... // Many more methods defined for Custom. 
    // (Positive and negative directions in 100 dimensions)

func main() {
    var many []Custom
    fmt.Println("Memory: ", foo.memory()) // Measure memory used.
    for i := 0; i < 10000; i++ {
        append(many, Custom{value: "nowhere"})
    } 
    fmt.Println("Memory: ", foo.memory()) // Measure memory used. 
}

2 个答案:

答案 0 :(得分:3)

当将具体类型分配给接口类型时,运行时会分配 itable 。具体类型和接口类型的 itable 将被缓存并用于以后的分配。

例如,此代码将分配一个itable:

type Volume interface {
    TurnItUp()
    TurnItDown()
}
var many []Volume
for i := 0; i < 10000; i++ {
    many = append(many, Custom{value: "nowhere"})
}

此代码将分配两个itables,一个用于(Custom,Upper),另一个用于(Custom,Downer):

type Upper interface {
    TurnItUp()
}
type Downer interface {
    TurnItDown()
}
var uppers []Upper
var downers []Downer
for i := 0; i < 10000; i++ {
    uppers = append(uppers, Custom{value: "nowhere"})
    downers = append(downers, Custom{value: "nowhere"})
}

因为问题中的示例没有为接口分配自定义值,所以不会创建itables。

运行时使用静态元数据数据来构造itables。静态数据被分配并初始化一次。

有关详细信息,请参阅Go Data Structures: Interfaces

答案 1 :(得分:3)

Bravada Zadada基本上回答了你的问题,但是在这里你是如何进行一项测试,显示某项行动导致的分配数量:

func TestMethods(t *testing.T) {
    mem := testing.AllocsPerRun(10000000, func() {
        _ = Custom{value: "nowhere"}
    })
    if mem != 0 {
        t.Errorf("creating an object allocated %v memory", mem)
    }
}

请参阅testing.AllocsPerRun文档。您可以使用接口,指针方法和其他方法进行类似的测试。