2014-10-11 117 views
1

虽然我知道在Go中可能不会习惯性地恐慌,但我想测试以确保函数在某些情况下发生混乱,而不是在其他情况下发生混乱。在Go中使用反射来检查兼容类型

函数的一个例子。

func PanicOnErr(potentialErr error) { 
    if potentialErr != nil { 
     panic(potentialErr) 
    } 
} 

以下是检查函数是否会出现混乱的实现。

func InvocationCausedPanic(f interface{}, params ...interface{}) bool { 
    // Obtain the function's signature. 
    reflectedFunc := reflect.ValueOf(f) 
    funcType := reflect.TypeOf(f) 

    if funcType.NumIn() != len(params) { 
     panic("InvocationCausedPanic called with a function and an incorrect number of parameter(s).") 
    } 

    reflectedParams := make([]reflect.Value, len(params)) 
    for paramIndex, paramValue := range params { 
     expectedType := funcType.In(paramIndex) 
     actualType := reflect.TypeOf(paramValue) 

     if actualType != expectedType { 
      errStr := fmt.Sprintf("InvocationCausedPanic called with a mismatched parameter type [parameter #%v: expected %v; got %v].", paramIndex, expectedType, actualType) 
      panic(errStr) 
     } 

     reflectedParams[paramIndex] = reflect.ValueOf(paramValue) 
    } 

    return invoke(reflectedFunc, reflectedParams) 
} 

func invoke(reflectedFunc reflect.Value, reflectedParams []reflect.Value) (panicked bool) { 
    defer func() { 
     if r := recover(); r != nil { 
      panicked = true 
     } 
    }() 

    reflectedFunc.Call(reflectedParams) 
    return 
} 

调用以下任何一项都会导致类型检查失败。

InvocationCausedPanic(PanicOnErr, errors.New("Some error.")) 
InvocationCausedPanic(PanicOnErr, nil) 

然而,似乎有可能同时使用nil和东西叫PanicOnErr通过调用errors.New生成(似乎是*errors.errorString类型)。

因此,有没有办法检查某些参数的类型是否适合调用某个函数?

尽管我知道可以使用延迟和恢复来更简单地测试函数,但我很好奇是否可以编写一个通用函数来接受任何函数和参数,并确定它是否导致恐慌(假设函数完成)。

相关转到游乐场: http://play.golang.org/p/qUG7OGuIbD

回答

1

使用此功能,以确定是否该参数是兼容的:

func compatible(actual, expected reflect.Type) bool { 
    if actual == nil { 
    k := expected.Kind() 
    return k == reflect.Chan || 
      k == reflect.Func || 
      k == reflect.Interface || 
      k == reflect.Map || 
      k == reflect.Ptr || 
      k == reflect.Slice 
    } 
    return actual.AssignableTo(expected) 
} 

playground

+1

谢谢。这解决了类型兼容性问题! – Deity 2014-10-12 00:38:01

+0

再次感谢您的帮助。我问过一个后续问题;也许你也会知道答案。 http://stackoverflow.com/questions/26321115 – Deity 2014-10-12 02:04:48