No Go runtime/proc.go
, há um trecho de código mostrado abaixo:
// funcPC retorna a entrada PC da função f.
// Supõe que f é um valor de função. Caso contrário, o comportamento é indefinido.
// CUIDADO: Nos programas com plugins, o funcPC pode retornar valores diferentes
// para a mesma função (porque na verdade existem várias cópias da
// mesma função no espaço de endereço). Para estar seguro, não use os
// resultados desta função em nenhuma expressão ==. É seguro
// usar o resultado como um endereço no qual iniciar a execução do código.
//go:nosplit
func funcPC(f interface{}) uintptr {
return **(**uintptr)(add(unsafe.Pointer(&f), sys.PtrSize))
}
O que eu não entendo é por que não usar * (* uintptr) em vez de ** (** uintptr)?
Então, escrevo um programa de teste abaixo para descobrir.
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))
}
O resultado de que p não é igual a p1 me deixa confusa. Por que o valor de p não é igual ao valor de p1 enquanto o tipo é o mesmo?
funcPC(p)
seria o valor . Qual é o sentido de ter um ponteiro para um ponteiro de qualquer maneira.
pp
apontar para p
, escrevendo para *pp
gravações p
e lendo *pp
leituras de p
. Se p
estiver no escopo, é claro que isso é um pouco bobo, já que você pode apenas ler ou escrever p
diretamente. Mas e se nãop
estiver no escopo, ou e se apontar para um ou (dependendo da lógica anterior), e você gostaria de usar ou atualizar o ponteiro que aponta para? pp
p
q
pp