使用反射调用一个带有空参数的函数会导致”使用零值参数调用”的恐慌。

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

Using reflection to call a function with a nil parameter results in a "Call using zero Value argument" panic

问题

我正在尝试测试一个接受"error"类型参数的函数。在某些情况下,该函数应该引发panic,我正在尝试测试这些场景。

然而,当我尝试在一个接受"type error"参数的函数中使用reflect.Call来调用一个nil值时,似乎会导致panic,并显示以下消息:

reflect: 使用零值参数进行调用

我找到了以下帖子,但我无法将其整合到我的函数中。

相关的Go Playground: http://play.golang.org/p/cYQMQ6amPH

在上面的playground中,我希望调用InvocationCausedPanic(PanicOnErr, nil)返回false,然而,reflect引发的panic导致了一个错误的结果。

我是否可以对InvocationCausedPanicinvoke函数进行任何修改,使其正常工作(同时保留其测试其他不能接受nil作为参数的函数的能力,比如接受字符串的函数)?

也许问题出在函数的调用方式上?

我尝试过像InvocationCausedPanic(PanicOnErr, new(error))InvocationCausedPanic(PanicOnErr, error(nil))这样的方法,但都没有成功。

感谢任何建议。

英文:

I'm trying to test a function that accepts a parameter of the type "error". The function should panic under certain situations and I'm trying to test scenarios.

However, when I try to use reflect.Call on a nil value (which can be passed into a function that accepts something of type "error"), it seems to result in a panic with the following message:

reflect: Call using zero Value argument

I have found the following posts but I am failing to integrate it into my function.

Relevant Go Playground: http://play.golang.org/p/cYQMQ6amPH

In the playground above, I would like the call to InvocationCausedPanic(PanicOnErr, nil) to return false, however, the above panic from reflect is causing a false positive.

Are there any modifications I can make to the InvocationCausedPanic or the invoke functions to make this work (while retaining its ability to test other functions that cannot accept nil as an argument - a function that accepts a string for instance)?

Perhaps the issue is in how the function is called?

I've tred things like InvocationCausedPanic(PanicOnErr, new(error)) or InvocationCausedPanic(PanicOnErr, error(nil)) to no avail.

Thanks for any advice.

答案1

得分: 4

如果参数值为nil,则使用函数参数类型的零值。

if paramValue == nil {
    reflectedParams[paramIndex] = reflect.New(expectedType).Elem()
} else {
    reflectedParams[paramIndex] = reflect.ValueOf(paramValue)
}

你可以简化代码,如果你计算了反射值,然后检查可分配性。通过这个改变,compatible函数就不再需要了。

for paramIndex, paramValue := range params {
    if paramValue == nil {
        reflectedParams[paramIndex] = reflect.New(expectedType).Elem()
    } else {
        reflectedParams[paramIndex] = reflect.ValueOf(paramValue)
    }
    expectedType := funcType.In(paramIndex)
    actualType := reflectedParams[paramIndex].Type()
    if !actualType.AssignableTo(expectedType) {
        errStr := fmt.Sprintf("InvocationCausedPanic called with a mismatched parameter type [parameter #%v: expected %v; got %v].", paramIndex, expectedType, actualType)
        panic(errStr)
    }
}

<kbd>playground</kbd>

英文:

If the parameter value is nil, then use a zero value of the function parameter type.

	if paramValue == nil {
		reflectedParams[paramIndex] = reflect.New(expectedType).Elem()
	} else {
		reflectedParams[paramIndex] = reflect.ValueOf(paramValue)
	}

<kbd>playground</kbd>

You can simplify the code if you compute the reflect value and then check assignability. With this change, the compatible function is not required.

for paramIndex, paramValue := range params {
	if paramValue == nil {
		reflectedParams[paramIndex] = reflect.New(expectedType).Elem()
	} else {
		reflectedParams[paramIndex] = reflect.ValueOf(paramValue)
	}
	expectedType := funcType.In(paramIndex)
    actualType := reflectedParams[paramIndex].Type()
	if !actualType.AssignableTo(expectedType) {
		errStr := fmt.Sprintf(&quot;InvocationCausedPanic called with a mismatched parameter type [parameter #%v: expected %v; got %v].&quot;, paramIndex, expectedType,actualType)
		panic(errStr)
	}
}

huangapple
  • 本文由 发表于 2014年10月12日 10:01:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/26321115.html
匿名

发表评论

匿名网友

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

确定