这个
fmt
包调用
Value.Pointer
获取函数地址。
让我们来看一个例子
Value.Pointer
函数的返回:
s0 := &Str{}
v0 := reflect.ValueOf(s0)
fmt.Printf("s0.Callme: %0x %0x\n", reflect.ValueOf(s0.Callme).Pointer(), s0.Callme)
fmt.Printf("v0.Method(0) %0x %0x\n", v0.Method(0).Pointer(), v0.Method(0))
s1 := &Str{}
v1 := reflect.ValueOf(s1)
fmt.Printf("s1.Callme %x %x\n", reflect.ValueOf(s1.Callme).Pointer(), s1.Callme)
fmt.Printf("v1.Method(0) %x %x\n", v1.Method(0).Pointer(), v1.Method(0))
输出是:
s0.Callme: 105240 105240
v0.Method(0) eee60 eee60
s1.Callme 105240 105240
v1.Method(0) eee60 eee60
这与问题中显示的模式匹配。
这个
function related code for Value.Pointer
是:
if v.flag&flagMethod != 0 {
// As the doc comment says, the returned pointer is an
// underlying code pointer but not necessarily enough to
// identify a single function uniquely. All method expressions
// created via reflect have the same underlying code pointer,
// so their Pointers are equal. The function used here must
// match the one used in makeMethodValue.
f := methodValueCall
return **(**uintptr)(unsafe.Pointer(&f))
}
p := v.pointer()
// Non-nil func value points at data block.
// First word of data block is actual code.
if p != nil {
p = *(*unsafe.Pointer)(p)
}
return uintptr(p)
一
reflect.Value
通过创建
method expression
在反射API中
flagMethod
方法位集。正如注释状态和代码所示,指针方法为以这种方式创建的所有方法表达式返回相同的值。
这个
反映价值
创建的
relect.ValueOf(s1.Callme)
没有
旗杆法
方法位集。在这种情况下,函数返回指向实际代码的指针。
产量
this program
显示所有组合:
type StrA struct {
I int
S string
}
func (s *StrA) Callme() {
fmt.Println("it is me")
}
type StrB struct {
I int
S string
}
func (s *StrB) Callme() {
fmt.Println("it is me")
}
s0A := &StrA{}
v0A := reflect.ValueOf(s0A)
s1A := &StrA{}
v1A := reflect.ValueOf(s0A)
fmt.Println("s0A.Callme ", reflect.ValueOf(s0A.Callme).Pointer())
fmt.Println("v0A.Method(0) ", v0A.Method(0).Pointer())
fmt.Println("s1A.Callme ", reflect.ValueOf(s1A.Callme).Pointer())
fmt.Println("v1A.Method(0) ", v1A.Method(0).Pointer())
s0B := &StrB{}
v0B := reflect.ValueOf(s0B)
s1B := &StrB{}
v1B := reflect.ValueOf(s0B)
fmt.Println("s0B.Callme ", reflect.ValueOf(s0B.Callme).Pointer())
fmt.Println("v0B.Method(0) ", v0B.Method(0).Pointer())
fmt.Println("s1B.Callme ", reflect.ValueOf(s1B.Callme).Pointer())
fmt.Println("v1B.Method(0) ", v1B.Method(0).Pointer())
输出:
s0A.Callme 1061824
v0A.Method(0) 978528
s1A.Callme 1061824
v1A.Method(0) 978528
s0B.Callme 1061952
v0B.Method(0) 978528
s1B.Callme 1061952
v1B.Method(0) 978528
我们可以观察到这个值。指针返回的所有值都相同
method expressions
通过反射API创建。这包括不同类型的方法。
我们也可以观察到
指针值
返回相同的值
方法表达式
在给定的类型和方法上。对于绑定到不同值的方法表达式,这是正确的。
这个
Value.Pointer documentation
说:
如果v的kind是func,则返回的指针是一个基础代码指针,但不一定足以唯一地标识单个函数。唯一的保证是当且仅当v为零func值时,结果为零。
鉴于此,应用程序无法可靠地使用value.pointer或通过
FMT
用于比较函数和方法的包。