【问题标题】:Does Golang run on a virtual machine?Golang 可以在虚拟机上运行吗?
【发布时间】:2015-09-25 16:49:32
【问题描述】:

说一些非常简单的 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 函数?

【问题讨论】:

  • 在检查库代码以查看fmtreflect 在打印它们时是否对函数指针值进行了任何修改后,我得出的结论是它们没有。 Go 实际上只是将您的代码映射到 VM 空间的最底部附近。 :)
  • 他不知道就问,为什么要投票给他?

标签: go


【解决方案1】:

Go 不在虚拟机上运行。

从语言规范来看,ptrptr2function values。它们可以称为ptr(1, 2)ptr2(1, 2, 3)

深入了解实现,变量ptrptr2 是指向函数值的指针。有关 func 值的信息,请参阅Function Call 设计文档。注意语言的“function”值和实现的“func”值之间的区别。

因为fmtindirects使用的reflectionAPI通过func值来获取打印指针,所以对fmt.Println(ptr)的调用打印出plus函数的实际地址。

【讨论】:

    【解决方案2】:

    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) 字节后出现以满足最佳对齐要求。

    出于好奇,下面是 func plusobjdump -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   
    

    【讨论】:

      【解决方案3】:

      它们是函数值:

      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
      

      【讨论】:

        猜你喜欢
        • 2017-02-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-17
        • 1970-01-01
        • 1970-01-01
        • 2020-06-21
        • 1970-01-01
        相关资源
        最近更新 更多