2014-10-11 2 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) 

Тем не менее, кажется, можно назвать PanicOnErr использованием как nil и что-то произвести, вызвав errors.New (кажется, типа *errors.errorString).

Таким образом, существует ли способ проверить, подходит ли тип некоторого параметра для вызова некоторой функции?

Хотя я знаю, что можно использовать отсрочку и восстановление для более простого тестирования функции, мне любопытно, можно ли написать общую функцию, которая может принимать любые функции и параметры и определять, привело ли это к паника (при условии, что функция завершена).

Соответствующая Go площадка: 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

+0

Еще раз спасибо за помощь. Я задал следующий вопрос; возможно, вы тоже знаете ответ на этот вопрос. http://stackoverflow.com/questions/26321115 – Deity

Смежные вопросы