Перейти к содержанию

Функции

Функция — единица повторного использования кода. В Go функции — это полноправные значения: их можно передавать в аргументы, возвращать и сохранять в переменные. Здесь — основы, без интерфейсов и дженериков.

Что должен понять

  • Как объявить функцию с аргументами и возвращаемым значением.
  • Что в Go функция может вернуть несколько значений.
  • Что такое named returns и когда их использовать.
  • Как принимать переменное число аргументов (variadic).
  • Что замыкание (closure) — это функция, которая «помнит» внешние переменные.

Базовая функция

func sum(a, b int) int {
    return a + b
}

func main() {
    fmt.Println(sum(3, 4))   // 7
}

Если несколько подряд аргументов одного типа — можно не повторять тип: func sum(a, b int).

Несколько возвращаемых значений

func divmod(a, b int) (int, int) {
    return a / b, a % b
}

q, r := divmod(10, 3)
fmt.Println(q, r)   // 3 1

Это используют для возврата (value, error) — стандартный паттерн в Go:

func parse(s string) (int, error) {
    return strconv.Atoi(s)
}

Named returns

Имена у возвращаемых значений = переменные внутри функции:

func split(sum int) (x, y int) {
    x = sum * 4 / 9
    y = sum - x
    return       // голый return: возвращает x, y
}

Используй умеренно. На длинных функциях named returns вредят читаемости — теряется явная связь возврата и значения.

Variadic — переменное число аргументов

func sumAll(nums ...int) int {
    total := 0
    for _, n := range nums {
        total += n
    }
    return total
}

sumAll(1, 2, 3)              // 6
nums := []int{1, 2, 3}
sumAll(nums...)              // распаковать слайс

fmt.Println сделан как раз через variadic.

Замыкания (короткое введение)

Замыкание — функция, которая «захватывает» внешнюю переменную:

func counter() func() int {
    n := 0
    return func() int {
        n++
        return n
    }
}

next := counter()
fmt.Println(next(), next(), next())   // 1 2 3

n живёт, пока жива возвращённая функция. Это тот же механизм, что у замыканий в JavaScript и Python.

Типичные ошибки

  • Забывают return в функции с возвращаемым значением — компилятор ловит это сразу.
  • Передают слайс в функцию, ждут что не изменится — а функция делает s[0] = 0. Слайс — это «окно», см. часть 2.
  • Злоупотребляют named returns в длинных функциях.

Критерии приёмки модуля

  • Реализована функция sum(a, b int) int.
  • Реализована функция, возвращающая (int, error) или (int, int).
  • Реализована variadic-функция sumAll(nums ...int) int.
  • Реализован счётчик через замыкание, как в примере.

Дальше: Структуры и методы.