Testing 使用反射调用带有nil参数的函数会导致;使用零值参数调用";惊恐

Testing 使用反射调用带有nil参数的函数会导致;使用零值参数调用";惊恐,testing,reflection,go,Testing,Reflection,Go,我正在尝试测试一个接受“error”类型参数的函数。在某些情况下,函数应该会死机,我正在尝试测试场景 但是,当我尝试对nil值(可以传递到接受“error”类型的函数)使用reflect.Call时,似乎会导致以下消息引起恐慌: reflect: Call using zero Value argument 我发现了以下帖子,但我没有将其整合到我的功能中 相关围棋场: 在上面的操场中,我希望调用InvocationCausedPanic(PanicOnErr,nil)返回false,但

我正在尝试测试一个接受“error”类型参数的函数。在某些情况下,函数应该会死机,我正在尝试测试场景

但是,当我尝试对
nil
值(可以传递到接受“error”类型的函数)使用
reflect.Call
时,似乎会导致以下消息引起恐慌:

reflect: Call using zero Value argument
我发现了以下帖子,但我没有将其整合到我的功能中

相关围棋场:

在上面的操场中,我希望调用
InvocationCausedPanic(PanicOnErr,nil)
返回
false
,但是,来自reflect的上述恐慌导致了误报

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

也许问题在于如何调用函数

我做过三次类似于
InvocationCausedPanic(paniconer,new(error))
InvocationCausedPanic(paniconer,error(nil))
的事情,但都没有用


谢谢您的建议。

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

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

如果计算反射值,然后检查可分配性,则可以简化代码。通过此更改,不需要
兼容
功能

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)
    }
}

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

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

如果计算反射值,然后检查可分配性,则可以简化代码。通过此更改,不需要
兼容
功能

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)
    }
}

谢谢你的回答。我已经实施了您建议的更改,效果很好。然而,我刚刚提出了一个有点做作的案例,其中对于不能接受nil的函数,类型不兼容检查不会失败。我认为这是因为在类型检查完成之前,nil被转换成一个兼容的零值。你看到什么优雅的解决方案了吗?相关操场:啊,明白了。再次感谢!谢谢你的回答。我已经实施了您建议的更改,效果很好。然而,我刚刚提出了一个有点做作的案例,其中对于不能接受nil的函数,类型不兼容检查不会失败。我认为这是因为在类型检查完成之前,nil被转换成一个兼容的零值。你看到什么优雅的解决方案了吗?相关操场:啊,明白了。再次感谢!