Golang是否在虚拟机上运行?

abg*_*don 12 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)
}
Run Code Online (Sandbox Code Playgroud)

这有以下输出:

0x2000
0x2020
Run Code Online (Sandbox Code Playgroud)

这里发生了什么?这看起来不像是一个函数指针,或任何类型的指针,可以在堆栈中找到.我也理解Go,虽然在线程部门提供了一些不错的低级功能,但也需要一个操作系统才能运行; C可以在所有计算机平台上运行,操作系统可以写入其中,而Go需要操作系统才能运行,实际上现在只能在少数操作系统上运行.常规函数指针是否意味着它可以在VM上运行?或者编译器是否只链接到低级C函数?

hob*_*bbs 10

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

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

0x400c00
0x400c20
Run Code Online (Sandbox Code Playgroud)

它们与您示例中的值不同,但仍然很低.检查已编译的代码:

$ nm test | grep 'T main.plus'
0000000000400c00 T main.plus
0000000000400c20 T main.plusPlus
Run Code Online (Sandbox Code Playgroud)

这些是函数的实际地址.func plus编译为仅19字节的代码,因此plusPlus稍后仅出现32(0x20)字节以满足最佳对齐要求.

为了好奇,这里是func plusfrom 的反汇编objdump -d,这应该消除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   
Run Code Online (Sandbox Code Playgroud)


Cer*_*món 9

Go不在虚拟机上运行.

从语言规范的视图,ptr并且ptr2函数值.它们可以被称为ptr(1, 2)ptr2(1, 2, 3).

深入了解实现,变量ptrptr2指向func值的指针.有关func值的信息,请参阅函数调用设计文档.请注意语言的"函数"值与实现的"func"值之间的区别.

由于fmt包使用的反射 API 通过func值间接获取指针以进行打印,因此调用将打印函数的实际地址.fmt.Println(ptr)plus


pet*_*rSO 2

它们是函数值:

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))
}
Run Code Online (Sandbox Code Playgroud)

输出:

0x20000
0x20020
3
6
Run Code Online (Sandbox Code Playgroud)