说一些非常简单的Golang代码:
django.utils.crypto
这有以下输出:
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)
}
这里发生了什么?这看起来不像是一个函数指针,或任何类型的指针,可以在堆栈中找到。我也理解Go,虽然在线程部门提供了一些不错的低级功能,但也需要一个操作系统才能运行; C可以在所有计算机平台上运行,操作系统可以写入其中,而Go需要操作系统才能运行,实际上现在只能在少数操作系统上运行。常规函数指针是否意味着它可以在VM上运行?或者编译器只链接到低级C函数?
答案 0 :(得分:9)
Go无法在虚拟机上运行。
从语言规范的角度来看,ptr
和ptr2
是function values。它们可以被称为ptr(1, 2)
和ptr2(1, 2, 3)
。
深入了解实现,变量ptr
和ptr2
是指向func值的指针。有关func值的信息,请参阅Function Call设计文档。注意语言的“函数”值和实现的“func”值之间的区别。
由于reflection包fmt使用indirects API通过func值来获取指针以进行打印,因此对fmt.Println(ptr)
的调用会打印出实际的地址。 plus
功能。
答案 1 :(得分:8)
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 plus
从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
答案 2 :(得分: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))
}
输出:
0x20000
0x20020
3
6