为什么在golang中,当将reflect.Value传递给接口时,不能使用Pointer()方法?

huangapple go评论79阅读模式
英文:

Why can not use Pointer() method when reflect.Value is passed to an interface in golang?

问题

我正在编写一个单元测试来检查包含函数的结构体的相等性。

以下是我的测试代码。
Go Playground

在比较时,我使用了一个名为GetFunctionName的函数来获取函数的名称。

func GetFunctionName(i interface{}) string {
	fmt.Printf("type in GetFunctionName: %v\n", reflect.TypeOf(reflect.ValueOf(i)))
	return runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name()
}

还编写了一个比较函数。

func SelectCompareStruct(got interface{}, want interface{}) {
	rvGot := reflect.ValueOf(got)
	rtGot := rvGot.Type()
	rvWant := reflect.ValueOf(want)
	rtWant := rvWant.Type()

	for i := 0; i < rtGot.NumField(); i++ {
		fieldGot := rtGot.Field(i)
		fieldWant := rtWant.Field(i)

		valueGot := rvGot.FieldByName(fieldGot.Name)
		valueWant := rvWant.FieldByName(fieldWant.Name)
		fmt.Printf("type in SelectCompareStruct: %v\n", reflect.TypeOf(reflect.ValueOf(valueGot)))

		// Works
		gotFuncNameInner := runtime.FuncForPC(valueGot.Pointer()).Name()
		wantFuncNameInner := runtime.FuncForPC(valueWant.Pointer()).Name()
		fmt.Printf("gotFuncNameInner:\n\t\t\t%v\nwantFuncNameInner:\n\t\t\t%v\n", gotFuncNameInner, wantFuncNameInner)

		// Does not work
		gotFuncName := GetFunctionName(valueGot)
		wantFuncName := GetFunctionName(valueWant)
		fmt.Printf("gotFuncName:\n\t%v\n wantFuncName:\n\t%v\n", gotFuncName, wantFuncName)
	}
}

你可以看到,当我直接获取函数的名称时,它可以工作。
然而,当我使用一个函数时,它就无法工作了。
尽管两者都是应用了Pointer()方法的reflect.Value类型。

是的,我可以将GetFunctionName的输入类型更改为reflect.Value以使其工作。
但这对其他用例来说并不好。我想要一个可以适用于各种情况的获取名称的函数。
最好能够将输入类型设为interface{}。

有人知道为什么吗?如何修复这个问题?

英文:

I am writing a unit test to check equality of struct that contains func.

Here are my test code.
Go Palyround

When comparing, I used a func named GetFunctionName to get function's name for going.

func GetFunctionName(i interface{}) string {
	fmt.Printf(&quot;type in GetFunctionName: %v\n&quot;, reflect.TypeOf(reflect.ValueOf(i)))
	return runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name()
}

Also a compare function was made.

func SelectCompareStruct(got interface{}, want interface{}) {
	rvGot := reflect.ValueOf(got)
	rtGot := rvGot.Type()
	rvWant := reflect.ValueOf(want)
	rtWant := rvWant.Type()

	for i := 0; i &lt; rtGot.NumField(); i++ {
		fieldGot := rtGot.Field(i)
		fieldWant := rtWant.Field(i)

		valueGot := rvGot.FieldByName(fieldGot.Name)
		valueWant := rvWant.FieldByName(fieldWant.Name)
		fmt.Printf(&quot;type in SelectCompareStruct: %v\n&quot;, reflect.TypeOf(reflect.ValueOf(valueGot)))

		// Works
		gotFuncNameInner := runtime.FuncForPC(valueGot.Pointer()).Name()
		wantFuncNameInner := runtime.FuncForPC(valueWant.Pointer()).Name()
		fmt.Printf(&quot;gotFuncNameInner:\n\t\t\t%v\nwantFuncNameInner:\n\t\t\t%v\n&quot;, gotFuncNameInner, wantFuncNameInner)

		// Does not work
		gotFuncName := GetFunctionName(valueGot)
		wantFuncName := GetFunctionName(valueWant)
		fmt.Printf(&quot;gotFuncName:\n\t%v\n wantFuncName:\n\t%v\n&quot;, gotFuncName, wantFuncName)
	}
}

You can see, when I write directly to get function's name, it works.
However, it does not work when using a func instead.
Although, both of which type that apply Pointer() method are reflect.Value type.

Yes, I can change input type of GetFunctionName to reflect.Value for working.
That's not good for other use cases. I want to make a function for getting name for versatility.
It will be beautiful to make input type interface{}.

Anyone have any idea why? And how to fix it?

答案1

得分: 1

问题是你在 reflect.Value 上调用了 reflect.Value。通过删除对 reflect.Value 的额外调用来修复。

func GetFunctionName(v reflect.Value) string {
    fmt.Printf("type in GetFunctionName: %v\n", v.Type())
    return runtime.FuncForPC(v.Pointer()).Name()
}

在 playground 上运行它:点击这里

英文:

The problem is that you are calling reflect.Value on a reflect.Value. Fix by removing the extra call to reflect.Value.

func GetFunctionName(v reflect.Value) string {
	fmt.Printf(&quot;type in GetFunctionName: %v\n&quot;, v.Type())
	return runtime.FuncForPC(v.Pointer()).Name()
}

Run it on the playground.

huangapple
  • 本文由 发表于 2021年9月28日 14:08:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/69356588.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定