Зачем из функции делать тип и как это работает?
У меня есть следующий пример использования функции как типа:
type testInt func(int) bool
func isOdd(integer int) bool {
if integer%2 == 0 {
return false
}
return true
}
func isEven(integer int) bool {
if integer%2 == 0 {
return true
}
return false
}
// передаем функцию `f` как аргумент в другую функцию
func filter(slice []int, f testInt) []int {
var result []int
for _, value := range slice {
if f(value) {
result = append(result, value)
}
}
return result
}
func main() {
slice := []int{1, 2, 3, 4, 5, 7}
fmt.Println("Срез = ", slice)
odd := filter(slice, isOdd) // используем функции как значения
fmt.Println("Нечетные элементы среза: ", odd)
even := filter(slice, isEven)
fmt.Println("Четные элементы среза: ", even)
}
Получается что мы передаём функции isOdd и isEven как значение (то есть передали данные которые должны выйти из функции. В данном примере - true/false), но какую роль тогда играет у нас конструкция type testInt func(int) bool ?
Ещё хотелось бы узнать где зачастую используется такие конструкции?
Ответы (1 шт):
type testInt func(int) bool - подобие интерфейса с единственной функцией (функциональный интерфейс в Java). Фактически вы объявляете тип функции, которую можно будет использовать как в качестве переменной или аргумента другой функции.
В представленном примере, вы сообщаете компилятору, что тип testInt является функцией, которая принимает единственный аргумент типа int и возвращает тип bool. Другими словами функция, которая была передана в качестве аргумента типа testInt должна соответствовать заявленному интерфейсу (принимать одно целое число и возвращать булевое значение).
Ваши функции isOdd и isEven удовлетворяют этому интерфейсу, так что они могут быть использованы в качестве аргумента функции filter. Если вы определите функцию как func isEven(integer float64) bool и попытаетесь передать её в качестве аргумента в filter, то будет ошибка компиляции с указанием того, что функция не соответствует типу testInt
cannot use isEven(type func(float64) bool) as type testInt
Когда вы передаёте isOdd, isEven в функцию filter вы получаете указатель на функцию, что позволяет вам подставлять различные реализации действий над данными, которые вы передали в filter. Это сокращает код, так как у вас в функции филтра заложена логика действий над коллекцией элементов, а непосредственное поведение над каждым объектом (в данном примере проверка на необходимое условие) вы передаёте во время вызова данной функции.