Golang空结构体

Golang中空结构体的地址如何分配,先看看测试结果:

package main

import "fmt"

func main() {
	Test()
}

func Test() {
	e1 := Empty{}
	e2 := Empty{}
	e3 := Empty{}

	fmt.Printf("e1 : %p\ne2 : %p\ne3 : %p", &e1, &e2, &e3)
}

type Empty struct {
}

输出结果:

PS E:\develop\gotest> go run .\main.go
e1 : 0x3cc578
e2 : 0x3cc578
e3 : 0x3cc578
PS E:\develop\gotest>

查看汇编信息:

        0x0036 00054 (.\main.go:10)     LEAQ    runtime.zerobase(SB), AX
        0x003d 00061 (.\main.go:10)     MOVQ    AX, "".&e1+112(SP)
        0x0042 00066 (.\main.go:11)     LEAQ    runtime.zerobase(SB), AX
        0x0049 00073 (.\main.go:11)     MOVQ    AX, "".&e2+104(SP)
        0x004e 00078 (.\main.go:12)     LEAQ    runtime.zerobase(SB), AX
        0x0055 00085 (.\main.go:12)     MOVQ    AX, "".&e3+96(SP)

看到在第10行、第11行、第12行都调用了 runtime.zerobase(SB)

翻看源码,在runtime/malloc.go文件中找到zerobase变量的声明,注释写明“所有0字节分配的基地址”

// base address for all 0-byte allocations
var zerobase uintptr

如果换成new一个对象,看看是什么样子:

func Test() {
	e1 := new(Empty)
	e2 := new(Empty)
	e3 := new(Empty)

	fmt.Printf("e1 : %p\ne2 : %p\ne3 : %p", &e1, &e2, &e3)
}
        0x0036 00054 (.\main.go:10)     LEAQ    type.*"".Empty(SB), AX
        0x003d 00061 (.\main.go:10)     MOVQ    AX, (SP)
        0x0041 00065 (.\main.go:10)     PCDATA  $1, $0
        0x0041 00065 (.\main.go:10)     CALL    runtime.newobject(SB)
        0x0046 00070 (.\main.go:10)     MOVQ    8(SP), DI
        0x004b 00075 (.\main.go:10)     MOVQ    DI, "".&e1+112(SP)
        0x0050 00080 (.\main.go:10)     PCDATA  $0, $-2
        0x0050 00080 (.\main.go:10)     CMPL    runtime.writeBarrier(SB), $0
        0x0057 00087 (.\main.go:10)     JEQ     94
        0x0059 00089 (.\main.go:10)     JMP     534
        0x005e 00094 (.\main.go:10)     LEAQ    runtime.zerobase(SB), AX
        0x0065 00101 (.\main.go:10)     MOVQ    AX, (DI)
        0x0068 00104 (.\main.go:10)     JMP     106
        0x006a 00106 (.\main.go:11)     PCDATA  $0, $-1
        0x006a 00106 (.\main.go:11)     LEAQ    type.*"".Empty(SB), AX
        0x0071 00113 (.\main.go:11)     MOVQ    AX, (SP)
        0x0075 00117 (.\main.go:11)     PCDATA  $1, $1
        0x0075 00117 (.\main.go:11)     CALL    runtime.newobject(SB)
        0x007a 00122 (.\main.go:11)     MOVQ    8(SP), DI
        0x007f 00127 (.\main.go:11)     MOVQ    DI, "".&e2+104(SP)
        0x0084 00132 (.\main.go:11)     PCDATA  $0, $-2
        0x0084 00132 (.\main.go:11)     CMPL    runtime.writeBarrier(SB), $0
        0x008b 00139 (.\main.go:11)     JEQ     146
        0x008d 00141 (.\main.go:11)     JMP     517
        0x0092 00146 (.\main.go:11)     LEAQ    runtime.zerobase(SB), AX
        0x0099 00153 (.\main.go:11)     MOVQ    AX, (DI)
        0x009c 00156 (.\main.go:11)     JMP     158
        0x009e 00158 (.\main.go:12)     PCDATA  $0, $-1
        0x009e 00158 (.\main.go:12)     LEAQ    type.*"".Empty(SB), AX
        0x00a5 00165 (.\main.go:12)     MOVQ    AX, (SP)
        0x00a9 00169 (.\main.go:12)     PCDATA  $1, $2
        0x00a9 00169 (.\main.go:12)     CALL    runtime.newobject(SB)
        0x00ae 00174 (.\main.go:12)     MOVQ    8(SP), DI
        0x00b3 00179 (.\main.go:12)     MOVQ    DI, "".&e3+96(SP)
        0x00b8 00184 (.\main.go:12)     PCDATA  $0, $-2
        0x00b8 00184 (.\main.go:12)     CMPL    runtime.writeBarrier(SB), $0
        0x00bf 00191 (.\main.go:12)     NOP
        0x00c0 00192 (.\main.go:12)     JEQ     199
        0x00c2 00194 (.\main.go:12)     JMP     495
        0x00c7 00199 (.\main.go:12)     LEAQ    runtime.zerobase(SB), AX
        0x00ce 00206 (.\main.go:12)     MOVQ    AX, (DI)
        0x00d1 00209 (.\main.go:12)     JMP     211

注意这里的代码:

// implementation of new builtin
// compiler (both frontend and SSA backend) knows the signature
// of this function
func newobject(typ *_type) unsafe.Pointer {
	return mallocgc(typ.size, typ, true)
}
// Allocate an object of size bytes.
// Small objects are allocated from the per-P cache's free lists.
// Large objects (> 32 kB) are allocated straight from the heap.
func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
	if gcphase == _GCmarktermination {
		throw("mallocgc called with gcphase == _GCmarktermination")
	}

	if size == 0 {
		return unsafe.Pointer(&zerobase)
	}
    
    ...
}

这里发现,当size等于0的时候,同样返回 zerobase。

所以在同一个进程中,空结构体创建的对象,指向同一地址,zerobase。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值