Функции

Функции в Go: несколько возвращаемых значений, именованные результаты и идиома (value, error).

Главная особенность функций Go — они умеют возвращать несколько значений, и именно на этом построена вся обработка ошибок в языке.

Объявление функции

Тип параметра пишется после имени, тип результата — после списка параметров. Если несколько параметров одного типа идут подряд, тип можно указать один раз.

package main

import "fmt"

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

func main() {
    fmt.Println(add(2, 3))
}

Вывод:

5

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

Это визитная карточка Go. Функция деления может вернуть и результат, и признак успеха. Никаких кортежей-обёрток и распаковки — синтаксис встроен в язык.

package main

import "fmt"

func divide(a, b int) (int, bool) {
    if b == 0 {
        return 0, false
    }
    return a / b, true
}

func main() {
    result, ok := divide(10, 2)
    fmt.Println(result, ok)

    _, ok = divide(10, 0) // _ отбрасывает ненужное значение
    fmt.Println(ok)
}

Вывод:

5 true
false

Подчёркивание _ — это «пустой идентификатор»: им отбрасывают значение, которое не нужно (например, индекс в цикле или вторую возвращаемую величину).

Идиома (value, error)

Самый частый паттерн в Go: функция возвращает результат и ошибку. По соглашению ошибка — всегда последнее значение. Подробно разберём ошибки в пятом разделе, но узнать форму стоит уже сейчас.

package main

import (
    "fmt"
    "strconv"
)

func main() {
    n, err := strconv.Atoi("42")
    if err != nil {
        fmt.Println("не число")
        return
    }
    fmt.Println(n + 1)
}

Вывод:

43

Именованные результаты

Результатам можно дать имена прямо в сигнатуре. Тогда они работают как заранее объявленные переменные, а пустой return вернёт их текущие значения. Это удобно для коротких функций и хорошо сочетается с defer.

package main

import "fmt"

func split(sum int) (x, y int) {
    x = sum * 4 / 9
    y = sum - x
    return // вернёт именованные x и y
}

func main() {
    fmt.Println(split(18))
}

Вывод:

8 10

Функции — это значения

Функцию можно присвоить переменной, передать в другую функцию и вернуть из неё. Замыкания захватывают переменные окружения — как в JavaScript или Python.

package main

import "fmt"

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

func main() {
    next := counter()
    fmt.Println(next(), next(), next())
}

Вывод:

1 2 3

Итог

  • Тип параметра пишется после имени; функция может вернуть несколько значений.
  • Идиома (value, error) — основа обработки ошибок; _ отбрасывает ненужное.
  • Функции — значения: их передают, возвращают и замыкают над переменными.
Проверьте себя
1. Сколько значений может вернуть функция в Go?
AТолько одно
BНе больше двух
CСколько угодно
DТолько через массив
2. Зачем нужен пустой идентификатор _?
AОбъявить константу
BОтбросить ненужное возвращаемое значение
CЗавершить программу
DИмпортировать пакет
3. По соглашению Go, где в списке результатов стоит error?
AПервым
BПоследним
CВ середине
DВ отдельной структуре
Поддержать проект