In Go's runtime/proc.go
wird unten ein Code gezeigt:
// funcPC gibt den Eingabe-PC der Funktion f zurück.
// Es wird davon ausgegangen, dass f ein Funktionswert ist. Ansonsten ist das Verhalten undefiniert.
// VORSICHT: In Programmen mit Plugins kann funcPC unterschiedliche
// Werte für dieselbe Funktion zurückgeben (da sich tatsächlich mehrere Kopien
derselben Funktion im Adressraum befinden). Verwenden Sie aus Sicherheitsgründen die
// Ergebnisse dieser Funktion in keinem == Ausdruck. Es ist nur sicher,
// das Ergebnis als Adresse zu verwenden, an der mit der Ausführung von Code begonnen werden soll.
//go:nosplit
func funcPC(f interface{}) uintptr {
return **(**uintptr)(add(unsafe.Pointer(&f), sys.PtrSize))
}
Was ich nicht verstehe ist, warum nicht * (* uintptr) anstelle von ** (** uintptr) verwenden?
Also schreibe ich unten ein Testprogramm, um es herauszufinden.
package main
import (
"fmt"
"unsafe"
)
func main(){
fmt.Println()
p := funcPC(test)
fmt.Println(p)
p1 := funcPC1(test)
fmt.Println(p1)
p2 := funcPC(test)
fmt.Println(p2)
}
func test(){
fmt.Println("hello")
}
func funcPC(f func()) uintptr {
return **(**uintptr)(unsafe.Pointer(&f))
}
func funcPC1(f func()) uintptr {
return *(*uintptr)(unsafe.Pointer(&f))
}
Das Ergebnis, dass p nicht gleich p1 ist, macht mich verwirrt. Warum ist der Wert von p nicht gleich dem Wert von p1, während ihr Typ gleich ist?
funcPC(p)
wäre. Was bringt es überhaupt, einen Zeiger auf einen Zeiger zu haben?
pp
verweist p
, Schreiben in *pp
Schreiben p
und Lesen aus *pp
Lesen von p
. Wennp
es im Umfang liegt, ist das natürlich ein bisschen albern, da man einfach direkt daraus lesen oder darauf schreiben kann p
. Aber was , wenn p
ist nicht in ihrem Umfang, oder was passiert , wenn pp
Punkte entweder p
oder q
(je nach früheren Logik), und Sie möchten , verwenden oder zu aktualisieren je nachdem , welche Zeiger pp
verweisen auf?