猿问

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

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


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,我可以像重置一样将obj放入池中r := Request{}吗?(我的意思是通过这个操作,struct obj 可以被重用,并且不会被 . 收集gc。)


牧羊人nacy
浏览 117回答 1
1回答

慕森王

规范:复合文字仅声明当您获取复合文字的地址时,它将指向一个未命名的变量,因此需要分配:获取复合文字的地址会生成一个指针,该指针指向使用该文字的值初始化的唯一变量。当您不获取文字的地址时,只需分配它,不需要分配,可以将结构值分配给已经分配内存的变量。为了验证,我们可以使用 Go 的测试框架。创建一个测试文件:package mainimport (&nbsp; &nbsp; "testing")type Request struct {&nbsp; &nbsp; Field string}var r = Request{Field: "a"}func BenchmarkStruct(b *testing.B) {&nbsp; &nbsp; for i := 0; i < b.N; i++ {&nbsp; &nbsp; &nbsp; &nbsp; r = Request{Field: "b"}&nbsp; &nbsp; }}var p = &Request{Field: "a"}func BenchmarkStructPtr(b *testing.B) {&nbsp; &nbsp; for i := 0; i < b.N; i++ {&nbsp; &nbsp; &nbsp; &nbsp; p = &Request{Field: "b"}&nbsp; &nbsp; }}运行它:go test -bench . -benchmem输出:BenchmarkStruct-4&nbsp; &nbsp; &nbsp; &nbsp;1000000000&nbsp; &nbsp; &nbsp; &nbsp;0.948 ns/op&nbsp; &nbsp; &nbsp; &nbsp;0 B/op&nbsp; &nbsp; 0 allocs/opBenchmarkStructPtr-4&nbsp; &nbsp; 32160099&nbsp; &nbsp; &nbsp; &nbsp; 37.3 ns/op&nbsp; &nbsp; &nbsp; &nbsp; 16 B/op&nbsp; &nbsp; 1 allocs/op如您所见,Request使用复合文字分配结构的值不需要分配。获取它的地址并分配需要 16 个字节分配(在我的 64 位架构上),这是Request包含单个string类型字段的结构的大小,字符串头是一个指针(8 个字节)和一个长度(8字节)。在 Go 中赋值总是会产生副本。因此,当您分配任何值(包括结构值)时,该值将被复制,并且您分配给它的变量不会引用原始值。
随时随地看视频慕课网APP

相关分类

Go
我要回答