将新结构重新分配给变量时,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 中的值总是复制一份。因此,当您分配任何值(包括结构值)时,该值将被复制并且原始值不会被您分配给它的变量引用。
当我将新的结构对象重新分配给现有变量时,地址没有改变。代码如下:
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 中的值总是复制一份。因此,当您分配任何值(包括结构值)时,该值将被复制并且原始值不会被您分配给它的变量引用。