将新结构重新分配给变量时,golang 会分配新内存吗?

Does golang allocate new memory when reassign a new struct to a variable?

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

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没有分配新的内存一样。那么当重新分配发生时 Go 会做什么?

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

Spec: Composite literals 仅声明当您获取复合文字的地址时,它将指向一个未命名的变量,因此需要分配:

Taking the address of a composite literal generates a pointer to a unique variable initialized with the literal's value.

当不取字面量的地址直接赋值时,不需要分配,struct值可以赋值给已经分配内存的变量。

为了验证,我们可以使用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 类型的字段,并且 string header 是一个指针(8 个字节)和一个长度(8 个字节)。

Assigning Go 中的值总是复制一份。因此,当您分配任何值(包括结构值)时,该值将被复制并且原始值不会被您分配给它的变量引用。