当把一个新的结构体重新分配给一个变量时,golang会分配新的内存吗?

问题描述 投票:-1回答:1

当我将一个新的结构体对象重新分配给一个现有的变量时,地址并没有改变。代码如下所示。

type Request struct {
    Field string
}
func main(){
    r := Request{Field: "a"}
    fmt.Printf("%p\n", &r)
    r = Request{Field: "b"}
    fmt.Printf("%p\n", &r)
}

输出:

0xc0004040d0
0xc0004040d0

这就像... Feild 被修改,而没有分配新的内存。那么当发生重新分配时,围棋会怎么做呢?

如果我想使用 sync.pool我可以把obj放到池子里,就像重设一样 r := Request{}? (我的意思是通过这个操作,struct obj可以重复使用,不会被 gc.)

go memory struct pool composite-literals
1个回答
2
投票

规范。复合字元 只说明当你取一个复合字面的地址时,将指向一个未命名的变量,所以需要分配。

读取复合字词的地址 的复合文字产生了一个指向唯一的 可变的 用literal的值初始化。

当你不取literal的地址只是赋值时,不需要分配,结构体的值可以分配给已经分配了内存的变量。

为了验证,我们可以使用Go的测试框架。创建一个测试文件。

package main

import (
    "testing"
)

type Request struct {
    Field string
}

var r = Request{Field: "a"}

func BenchmarkStruct(b *testing.B) {
    for i := 0; i < b.N; i++ {
        r = Request{Field: "b"}
    }
}

var p = &Request{Field: "a"}

func BenchmarkStructPtr(b *testing.B) {
    for i := 0; i < b.N; i++ {
        p = &Request{Field: "b"}
    }
}

用它来运行:

go test -bench . -benchmem

输出

BenchmarkStruct-4       1000000000       0.948 ns/op       0 B/op    0 allocs/op
BenchmarkStructPtr-4    32160099        37.3 ns/op        16 B/op    1 allocs/op

正如你所看到的,分配一个你的值 Request 使用复合字元的结构不需要分配。取它的地址并分配需要16个字节的分配(在我的64位架构上),这就是你的 Request 结构,其中包含一个单字段的 string 型,以及 串头 是一个指针(8个字节)和一个长度(8个字节)。

赋值 的值总是会进行复制。所以当你分配任何值(包括结构体的值)时,该值将被复制,而原始值不会被你分配给的变量引用。

© www.soinside.com 2019 - 2024. All rights reserved.