abgordon
abgordon

Reputation: 687

Does Golang run on a virtual machine?

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

Answers (3)

Thundercat
Thundercat

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

hobbs
hobbs

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

peterSO
peterSO

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

Related Questions