Global uninitialized symbols like globalInt
are stored in the BSS segment, close to the data segment, in the lower address space of the program.
You can check the addresses of program symbols with the nm
utility:
$ go build main.go
$ go tool nm main | grep globalInt
Outputs:
118e210 B main.globalInt
The first hex in the output is the address of the symbol, which is what will be printed when you run the program. E.g. on my machine:
$ ./main
0xc000124008
0x118e210 <--- same as nm output
The letter B
after the hex stands for bss segment symbol
.
If you explicitly initialize the variable in the source code, like var globalInt int = 600
the output of nm
will show:
114b268 D main.globalInt
where now D
stands for data segment symbol
.
Anyway all these are in the lower address space of the program. The scopedInt
doesn't pass escape analysis and is allocated on the heap, where its address will be higher than the global var.
Consider that all this is implementation-dependent. The specs don't mandate where to allocate objects.
If you compile and run the same program with TinyGo, the output will not look alike:
$ tinygo build -o tinymain main.go
$ ./tinymain
0x1158bf040
0x1061f3ca8