Каждая функция имеет определенный тип, который складывается из списка типов параметров и списка типов возвращаемых рехультатов. Например, возьмем следующую функцию:
func add(x int, y int) int{ return x + y }Эта функция представляет тип func(int, int) int. Этому же типу будет соответствовать следующая функция:
func multiply(x int, y int) int{ return x * y }
Хотя эта функция называется иначе, выполняет другие действия, но по типу параметров и по типу возвращаемого результата она соответствует выше указанному типу функции.
Возьмем еще одну функцию:
func display(message string){ fmt.Println(message) }
Эта функция имеет тип func(string). То есть опять же вначале идет слово func, а затем в скобках типы параметров. Так как функция не возвращает никакого результата, то соответственно возвращаемый тип не указывается.
Но какое значение имеет тип функции? Это значит, что мы можем определять переменные или параметры функций, которые будут представлять определенный тип функциии. То есть фактически переменная может быть функцией. Например:
package main import "fmt" func add(x int, y int) int{ return x + y } func main() { var f func(int, int) int = add fmt.Println(f(3, 4)) var x = f(4, 5) // 9 fmt.Println(x) }
Здесь переменная f имеет тип func(int, int) int
, то есть представляет любую функцию, которая принимает два параметра типа int и
возвращает значение типа int. Поэтому мы можем присвоить этой переменной функцию add, которая соответствует данному типу:
var f func(int, int) int = add
После этого мы можем вызывать присвоенную функцию через переменную, передавая нужные значения для ее параметров:
var x = f(4, 5) // 9
При этом переменная может изменять функцию, на которую она указывает, но при этому функция обязательно должна соответствовать ее типу:
package main import "fmt" func add(x int, y int) int{ return x + y} func multiply(x int, y int) int{ return x * y} func display(message string){ fmt.Println(message) } func main() { f := add //или так var f func(int, int) int = add fmt.Println(f(3, 4)) // 7 f = multiply // теперь переменная f указывает на функцию multiply fmt.Println(f(3, 4)) // 12 // f = display // ошибка, так как функция display имеет тип func(string) var f1 func(string) = display // норм f1("hello") }
Также функция может передаваться в качестве параметра в другую функцию. Например:
package main import "fmt" func add(x int, y int) int { return x + y } func multiply(x int, y int) int { return x * y } func action(n1 int, n2 int, operation func(int, int) int){ result := operation(n1, n2) fmt.Println(result) } func main() { action(10, 25, add) // 35 action(5, 6, multiply) // 30 }
Здесь функция action
принимает три параметра. Первые два параметра - числа, а третий параметр - функция, которая соответствует типу:
func(int , int) int
. То есть третий параметр представляет некоторое действие и может быть представлен любой функцией, которая принимает два значения типа int и возвращает также
значение типа int. Для примера здесь как раз определены две подобных функции, которые соответствуют данному типу: add и multiply. Через имя параметра operation
мы сможем вызывать данную функцию.
Или еще один пример:
package main import "fmt" func isEven(n int) bool{ return n % 2 == 0 } func isPositive(n int) bool{ return n > 0 } func sum(numbers []int, criteria func(int) bool) int{ result := 0 for _, val := range numbers{ if(criteria(val)){ result += val } } return result } func main() { slice := []int{-2, 4, 3, -1, 7, -4, 23} sumOfEvens := sum(slice, isEven) // сумма четных чисел fmt.Println(sumOfEvens) // -2 sumOfPositives := sum(slice, isPositive) // сумма положительных чисел fmt.Println(sumOfPositives) // 37 }
Здесь функция sum вычисляет сумму элементов среза. Но н всех элементов, а только тех, которые соответствуют условию. Условие передается в виде функции в качестве второго параметра.
Условие должно соответствовать функции типа func(int) bool
. То есть функция должна принимать в качестве параметра значение типа int и возвращать значение типа bool, которое указывает,
соответствовует ли переданное число условию.
Для примера здесь также определены две вспомогательные функции: isEven (возвращает true, если число четное) и isPositive (возвращает true, если число
положительное). Эти функции соответствуют типу func(int) bool
, поэтому их можно использовать в качестве условия.
Функция также может возвращаться из другой функции в качестве результата:
package main import "fmt" func add(x int, y int) int{ return x + y} func subtract(x int, y int) int{ return x - y} func multiply(x int, y int) int{ return x * y} func selectFn(n int) (func(int, int) int){ if n==1 { return add }else if n==2{ return subtract }else{ return multiply } } func main() { f := selectFn(1) fmt.Println(f(3, 4)) // 7 f = selectFn(3) fmt.Println(f(3, 4)) // 12 }
Здесь в зависимости от значения параметра функция selectFn возвращает одну из трех функций: add, subtract или multiply.