Golang是否在虚拟机上运行?
对于一些非常简单的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) }
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真的只是将代码映射到虚拟机空间的最底层附近。:)他不知道,并问,为什么投票否决他?