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

如何在内存中分配Go类型方法集?,go,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

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. 
}
键入自定义结构{
值字符串
}
func(c自定义)TurnItUp(){
c、 value=“向上”
}
func(c自定义)拒绝(){
c、 value=“向下”
}
... // 为自定义定义了更多方法。
//(100维正方向和负方向)
func main(){
var多[]自定义
fmt.Println(“内存:,foo.Memory())//测量使用的内存。
对于i:=0;i<10000;i++{
追加(许多,自定义{值:“无处”})
} 
fmt.Println(“内存:,foo.Memory())//测量使用的内存。
}
当一个具体类型被分配给一个接口类型时,运行时会分配一个itable。具体类型和接口类型的itable将被缓存,并在以后的分配中使用

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

type Volume interface {
    TurnItUp()
    TurnItDown()
}
var many []Volume
for i := 0; i < 10000; i++ {
    many = append(many, Custom{value: "nowhere"})
}
类型卷接口{
TurnItUp()
拒绝
}
var多[]卷
对于i:=0;i<10000;i++{
many=append(many,自定义{value:“nowhere”})
}
此代码将分配两个iTable,一个用于(Custom,Upper),另一个用于(Custom,Downer):

类型上层接口{
TurnItUp()
}
类型下行接口{
拒绝
}
var uppers[]Upper
var下行器[]下行器
对于i:=0;i<10000;i++{
uppers=append(uppers,自定义{value:“nowhere”})
downers=append(downers,自定义{value:“无处”})
}
因为问题中的示例没有为接口指定自定义值,所以不会创建itables

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

有关更多详细信息,请参阅。

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

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

type Volume interface {
    TurnItUp()
    TurnItDown()
}
var many []Volume
for i := 0; i < 10000; i++ {
    many = append(many, Custom{value: "nowhere"})
}
类型卷接口{
TurnItUp()
拒绝
}
var多[]卷
对于i:=0;i<10000;i++{
many=append(many,自定义{value:“nowhere”})
}
此代码将分配两个iTable,一个用于(Custom,Upper),另一个用于(Custom,Downer):

类型上层接口{
TurnItUp()
}
类型下行接口{
拒绝
}
var uppers[]Upper
var下行器[]下行器
对于i:=0;i<10000;i++{
uppers=append(uppers,自定义{value:“nowhere”})
downers=append(downers,自定义{value:“无处”})
}
因为问题中的示例没有为接口指定自定义值,所以不会创建itables

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


有关更多详细信息,请参阅。

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)
    }
}

见文件。您可以使用接口、指针方法等进行类似的测试。

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)
    }
}
见文件。您可以使用接口、指针方法等进行类似的测试。

是的,在“计算Itable”部分的文档中,它讨论了如何计算每个类型的Itable,而不是每个实例。围棋的人并不笨;应该没问题。是的,在“计算Itable”部分的文档中,它讨论了计算每个类型的Itable,而不是每个实例。围棋的人并不笨;应该没问题。