Trong Go's runtime/proc.go
, có một đoạn mã hiển thị bên dưới:
// funcPC trả về PC nhập của hàm f.
// Giả sử f là giá trị func. Nếu không thì hành vi là không xác định.
// CẨN THẬN: Trong các chương trình có plugin, funcPC có thể trả về các giá trị khác nhau
// cho cùng một hàm (vì thực tế có nhiều bản sao của
// cùng một hàm trong không gian địa chỉ). Để an toàn, không sử dụng
// kết quả của hàm này trong bất kỳ biểu thức == nào. Chỉ an toàn khi
sử dụng kết quả làm địa chỉ để bắt đầu thực thi mã.
//go:nosplit
func funcPC(f interface{}) uintptr {
return **(**uintptr)(add(unsafe.Pointer(&f), sys.PtrSize))
}
Điều tôi không hiểu là tại sao không sử dụng * (* uintptr) thay vì ** (** uintptr)?
Vì vậy, tôi viết một chương trình thử nghiệm dưới đây để tìm ra.
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))
}
Kết quả mà p không bằng p1 làm tôi bối rối. Tại sao giá trị của p không bằng giá trị của p1 trong khi loại của chúng giống nhau?
funcPC(p)
nó sẽ là gì. Dù sao thì việc có một con trỏ đến một con trỏ là gì.
pp
trỏ đến p
, viết để *pp
viết p
và đọc từ *pp
đọc từ p
. Nếu p
trong phạm vi, điều đó tất nhiên là hơi ngớ ngẩn vì bạn chỉ có thể đọc từ, hoặc viết p
trực tiếp. Nhưng nếu p
là không trong phạm vi, hoặc những gì nếu pp
điểm để một trong hai p
hoặc q
(tùy thuộc vào logic trước đó), và bạn muốn sử dụng hoặc cập nhật bất cứ con trỏ pp
điểm đến?