2015-07-08 12 views
6

sagen für einige sehr einfache Golang Code:Läuft Golang auf einer virtuellen Maschine?

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) 
} 

Dies hat die folgende Ausgabe:

0x2000 
0x2020 

Was ist hier los? Dies sieht nicht wie ein Funktionszeiger oder irgendeine Art von Zeiger für diese Angelegenheit aus, die man im Stapel finden würde. Ich verstehe auch, dass Go, obwohl es einige nette Low-Level-Funktionalität in der Threading-Abteilung bietet, auch ein Betriebssystem benötigt, damit es funktioniert; C ist auf allen Computerplattformen funktionsfähig, und Betriebssysteme können darin geschrieben werden, während Go ein Betriebssystem benötigt, um zu funktionieren, und in der Tat funktioniert es nur auf einigen wenigen Betriebssystemen. Bedeuten die sehr regelmäßigen Funktionszeiger, dass dies auf einer VM funktioniert? Oder ist der Compiler nur mit C-Funktionen auf niedriger Ebene verbunden?

+1

Nachdem in der Bibliothek Code überprüft, ob 'fmt' zu sehen oder "reflect" hat beim Ausdrucken irgendwelche Änderungen an den Funktionszeigerwerten vorgenommen, ich kam zu dem Schluss, dass dies nicht der Fall ist. Go mappt Ihren Code ganz einfach ganz unten im VM-Bereich. :) – hobbs

+1

Er weiß es nicht und fragt, warum ihn ablehnen? – vuhung3990

Antwort

2

Sie sind Funktionswerte:

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)) 
} 

Ausgang:

0x20000 
0x20020 
3 
6 
7

Go nicht auf einer virtuellen Maschine ausgeführt.

Aus der Sicht der Sprachspezifikation, ptr und ptr2 sind function values. Sie können als ptr(1, 2) und ptr2(1, 2, 3) bezeichnet werden. Die Variablen ptr und ptr2 sind Zeiger auf func-Werte. Informationen zu Funktionswerten finden Sie im Dokument Function Call. Beachten Sie die Unterscheidung zwischen dem Funktionswert der Sprache und dem func-Wert der Implementierung.

Da die relflection API von dem fmt Paket verwendet indirects durch die func Werte um den Zeiger zu bekommen zu drucken, wird der Anruf an fmt.Println(ptr) druckt die aktuelle Adresse der plus Funktion.

6

Go wird nicht auf einer virtuellen Maschine ausgeführt. Das sind die tatsächlichen Adressen der Funktionen.

Auf meinem Rechner (go 1.4.1, Linux AMD64) das Programm druckt

0x400c00 
0x400c20 

, die in Ihrem Beispiel von den Werten verschieden sind, aber immer noch ziemlich niedrig. Überprüfen des kompilierten Codes:

$ nm test | grep 'T main.plus' 
0000000000400c00 T main.plus 
0000000000400c20 T main.plusPlus 

Dies sind die tatsächlichen Adressen der Funktionen. func plus kompiliert zu nur 19 Bytes Code, so erscheint plusPlus nur 32 (0x20) Bytes später, um optimale Ausrichtungserfordernisse zu erfüllen.

Aus Gründen der Neugier, hier ist die Demontage von func plus von objdump -d, die alle Zweifel zerstreuen sollen, die Go aber nativen Code zu etwas kompilieren:

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 
Verwandte Themen