Reputation: 687
say for some very simple Golang code:
package main
import "fmt"
func plus( a int, b int) int {
return a+b
}
func plusPlus(a,b,c int) int {
return a +b + c
}
func main() {
ptr := plus
ptr2 := plusPlus
fmt.Println(ptr)
fmt.Println(ptr2)
}
This has the following output:
0x2000
0x2020
What is going on here? This doesn't look like a function pointer, or any kind of pointer for that matter, that one would find in the stack. I also understand that Go, while offering some nice low level functionality in the threading department, also requires an OS for it to function; C is functional across all computer platforms and operating systems can be written in it while Go needs an operating system to function and in fact only works on a few OS right now. Do the very regular function pointers mean that this works on a VM? Or is the compiler just linked to low level C functions?
Upvotes: 27
Views: 23784
Reputation: 121059
Go does not run on a virtual machine.
From the view of the language specification, ptr
and ptr2
are function values. They can be called as ptr(1, 2)
and ptr2(1, 2, 3)
.
Diving down into the implementation, the variables ptr
and ptr2
are pointers to func values. See the Function Call design document for information on func values. Note the distinction between the language's "function" value and the implementation's "func" value.
Because the reflection API used by the fmt package indirects through the func values to get the pointer to print, the call tofmt.Println(ptr)
prints the actual address of the plus
function.
Upvotes: 17
Reputation: 240314
Go doesn't run on a virtual machine. Those are the actual addresses of the functions.
On my machine (go 1.4.1, Linux amd64) the program prints
0x400c00
0x400c20
which are different from the values in your example, but still pretty low. Checking the compiled code:
$ nm test | grep 'T main.plus'
0000000000400c00 T main.plus
0000000000400c20 T main.plusPlus
these are the actual addresses of the functions. func plus
compiles to a mere 19 bytes of code, so plusPlus
appears only 32 (0x20) bytes later to satisfy optimal alignment requirements.
For the sake of curiosity, here's the disassembly of func plus
from objdump -d
, which should dispell any doubts that Go compiles to anything but native code:
0000000000400c00 <main.plus>:
400c00: 48 8b 5c 24 08 mov 0x8(%rsp),%rbx
400c05: 48 8b 6c 24 10 mov 0x10(%rsp),%rbp
400c0a: 48 01 eb add %rbp,%rbx
400c0d: 48 89 5c 24 18 mov %rbx,0x18(%rsp)
400c12: c3 retq
Upvotes: 13
Reputation: 166714
They are function values:
package main
import "fmt"
func plus(a int, b int) int {
return a + b
}
func plusPlus(a, b, c int) int {
return a + b + c
}
func main() {
funcp := plus
funcpp := plusPlus
fmt.Println(funcp)
fmt.Println(funcpp)
fmt.Println(funcp(1, 2))
fmt.Println(funcpp(1, 2, 3))
}
Output:
0x20000
0x20020
3
6
Upvotes: 2