Таким образом, вы определенно находитесь на правильном пути с идеей возврата куска нулевого типа интерфейса. Тем не менее, вы столкнулись с проблемами при попытке доступа к определенным членам или вызова определенных методов, потому что вы не будете знать, какой тип вы ищете. Вот где утверждают утверждения типа. Чтобы продлить ваш код немного:
getPerson(typ string, field string, val string) []Person {
slice := getItems(typ, field, val)
output := make([]Person, 0)
i := 0
for _, item := range slice {
// Type assertion!
thing, ok := item.(Person)
if ok {
output = append(output, thing)
i++
}
}
return output
}
Так что, что делает это он выполняет общий поиск, а затем отсеивает только те элементы, которые имеют правильный тип. В частности, утверждение типа:
thing, ok := item.(Person)
проверяет, является ли переменная item
имеет тип Person
, и если да, то она возвращает значение и верно, в противном случае она возвращает ноль и ложь (таким образом, проверка хорошо говорит нам, если утверждение преуспело).
Вы можете, если хотите, сделать еще один шаг и определить функцию getItems()
с точки зрения другой булевой функции. В принципе идея будет иметь getItems()
запустить функцию передать его по каждому элементу в базе данных, и только добавить, что элемент результатов при работе функции на элемент возвращает истину:
getItem(critera func(interface{})bool) []interface{} {
output := make([]interface{}, 0)
foreach _, item := range database {
if criteria(item) {
output = append(output, item)
}
}
}
(честно говоря, если бы это было меня, я бы сделал гибрид из двух, который принимает функцию критериев, но также принимает строки полей и значений)
На самом деле я бы использовал функцию коллектора, которая делает для меня добавление. Функция может закрываться над срезом [] и выполнять добавление добавления к этому фрагменту, если утверждение типа соответствует. Это будет работать более универсально, чем getItem, который возвращает результаты и будет более безопасным, поскольку «выход» может быть типизированным срезом. –
Да, но это не значит, что вы не можете предсказать тип вывода, поэтому он должен быть интерфейсом nil (или его срезом)? Возможно, я не понимаю, какие изменения вы предлагаете ...? – joshlf
См. Мой ответ для подробного объяснения :-). –