当我将一个新的struct对象重新分配到一个现有变量时,地址不会改变。代码如下:
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
,我可以像r := Request{}
一样将obj放入重置池吗?(我的意思是,使用此操作,结构obj可以重用,不会被gc
收集。)
发布于 2020-05-27 10:36:33
规范:复合文字只指出,当您获取复合文本的地址时,它将指向一个未命名的变量,因此需要分配:
当您不接受文字的地址时,只分配它,不需要分配,可以将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
类型的字段,而字符串标头是一个指针(8个字节)和一个长度(8个字节)。
Go中的赋值值总是复制。因此,当您赋值任何值(包括结构值)时,将复制该值,并且分配给它的变量不会引用原始值。
https://stackoverflow.com/questions/62039592
复制相似问题