Golang是否在虚拟机上运行?

Golang是否在虚拟机上运行?,go,Go,对于一些非常简单的Golang代码: 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) }

对于一些非常简单的Golang代码:

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)
}
它具有以下输出:

0x2000
0x2020

这是怎么回事?这看起来不像是一个函数指针,或者任何一种在堆栈中可以找到的指针。我也明白,Go虽然在线程部门提供了一些不错的低级功能,但它也需要一个操作系统才能正常工作;C可以在所有的计算机平台上运行,操作系统可以在其中编写,而Go需要一个操作系统来运行,事实上目前只在少数几个操作系统上运行。非常规则的函数指针是否意味着它可以在VM上工作?或者编译器只是链接到低级C函数?

它们是函数值:

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))
}
输出:

0x20000
0x20020
3
6

Go不在虚拟机上运行

从语言规范的角度来看,
ptr
ptr2
是。它们可以称为
ptr(1,2)
ptr2(1,2,3)

深入到实现中,变量
ptr
ptr2
是指向func值的指针。有关func值的信息,请参见设计文档。注意语言的“function”值和实现的“func”值之间的区别


由于包使用的API通过func值获取指向打印的指针,因此对
fmt.Println(ptr)
的调用将打印
plus
函数的实际地址。

Go不会在虚拟机上运行。这些是函数的实际地址

在我的机器(go 1.4.1,Linux amd64)上,程序打印

0x400c00
0x400c20
与示例中的值不同,但仍然非常低。检查编译的代码:

$ nm test | grep 'T main.plus'
0000000000400c00 T main.plus
0000000000400c20 T main.plusPlus
这些是函数的实际地址
func plus
编译为仅19字节的代码,因此
plusPlus
仅在32(0x20)字节后出现,以满足最佳对齐要求

出于好奇,这里是对
objdump-d
中的
func plus
的反汇编,这应该可以消除Go编译为非本机代码的任何疑问:

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   
0000000000 400C00:
400c00:48 8b 5c 24 08 mov 0x8(%rsp),%rbx
400c05:48 8b 6c 24 10 mov 0x10(%rsp),%rbp
400c0a:48 01 eb添加%rbp,%rbx
400c0d:48 89 5c 24 18 mov%rbx,0x18(%rsp)
400c12:c3 retq

在检查库代码以查看打印时
fmt
reflect
是否对函数指针值进行了任何修改后,我得出结论,它们没有。Go真的只是将代码映射到虚拟机空间的最底层附近。:)他不知道,并问,为什么投票否决他?