2014-10-11 78 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