Функции в языке Go как аргументы

Функции в Go

В Go функции являются объектами первого класса; их можно присваивать, передавать и использовать так же, как обычные переменные. Передача функции в качестве аргумента другой функции — распространённый шаблон программирования в Go, часто используемый в таких сценариях, как обратные вызовы и паттерн «стратегия».


Функция, присвоенная переменной

Функцию можно присвоить переменной, и функцию можно вызвать через эту переменную:

Пример

package main

import (
    "fmt"
    "math"
)

func main() {
    /* Присвоить анонимную функцию переменной getSquareRoot */
    getSquareRoot := func(x float64) float64 {
        return math.Sqrt(x)
    }

    /* Вызвать функцию через переменную */
    fmt.Println(getSquareRoot(9))   // Вывод: 3
    fmt.Println(getSquareRoot(16))  // Вывод: 4
}

Результат выполнения приведённого выше кода:

3
4

Передача функций в качестве аргументов

При передаче функции в качестве аргумента другой функции принимающая функция должна объявить соответствующий параметр типа функции. В следующем примере определяетсяapplyфункция, которая принимает функцию операции и два операнда, выполняя любую заданную операцию над этими двумя числами:

Пример

package main

import (
    "fmt"
    "math"
)

/* Определяем функцию, которая принимает параметр op типа функции */
/* тип op — func(float64, float64) float64, то есть он принимает два параметра float64 и возвращает float64 */
func apply(op func(float64, float64) float64, a, b float64) float64 {
    return op(a, b)
}

func main() {
    /* Определяем функцию сложения */
    add := func(a, b float64) float64 {
        return a + b
    }

    /* Определите функцию умножения */
    multiply := func(a, b float64) float64 {
        return a * b
    }

    /* Передайте функцию add как фактический аргумент в apply */
    fmt.Println(apply(add, 3, 4))       // Вывод: 7

    /* Передайте функцию multiply как фактический аргумент в apply */
    fmt.Println(apply(multiply, 3, 4))  // Вывод: 12

    /* Вы также можете передать анонимную функцию напрямую */
    fmt.Println(apply(func(a, b float64) float64 {
        return math.Pow(a, b) // a в степени b
    }, 2, 10))                          // Вывод: 1024
}

Результат выполнения приведённого выше кода:

7
12
1024

Практическое применение: пользовательские правила сортировки

Одно из самых распространённых применений функций в качестве аргументов — пользовательские правила сортировки. Стандартная библиотека Gosort.SliceОна принимает функцию сравнения в качестве параметра:

Пример

package main

import (
    "fmt"
    "sort"
)

func main() {
    nums := []int{5, 2, 8, 1, 9, 3}

    /* Передайте функцию сравнения в качестве фактического аргумента в sort.Slice, чтобы отсортировать от наименьшего к наибольшему */
    sort.Slice(nums, func(i, j int) bool {
        return nums[i] < nums[j]
    })
    fmt.Println("Ascending:", nums)  // Вывод: Ascending: [1 2 3 5 8 9]

    /* Передайте другую функцию сравнения, чтобы отсортировать от наибольшего к наименьшему */
    sort.Slice(nums, func(i, j int) bool {
        return nums[i] > nums[j]
    })
    fmt.Println(Descending:, nums)  // Вывод: descending: [9 8 5 3 2 1]
}

Результат выполнения приведённого выше кода:

升序:[1 2 3 5 8 9]
降序:[9 8 5 3 2 1]

Передавая разные функции в качестве аргументов, ту жеsort.Sliceпозволяет реализовать совершенно иную логику сортировки. Именно в этом заключается основная ценность функций как аргументов —параметризация поведения, делающая код более гибким и повторно используемым.。

Функции в Go

Другие расширения