Skip to content

Files

lesson1

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
Apr 6, 2023

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

Объявление функции имеет имя, список параметров, необязательный список результатов и тело:

func имя(список параметров) (список результатов) {
    тело
}

Список параметров указывает имена и типы параметров функции, которые являются локальными переменными. Их значения (аргументы), поставляются вызывающей функцией. Список результатов указывает типы значений, возвращаемые функцией. Если функция возвращает один неименованный результат или вовсе не возвращает результатов, скобки необязательны и обычно опускаются. Полное отсутствие списка результатов указывает на объявление функции, которая не возвращает никакого значения и вызывается только для выполнения некоторых действий.

В функции hypot x и y являются параметрами в объявлении функции, 3 и 4 - аргументами вызова, а возвращает функция значение float64:

func hypot(x, y, float64) float64 {
    return math.Sqrt(x*x + y*y)
}

fmt.Println(hypot(3, 4)) // "5"

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

Функция, которая имеет список результатов, должна заканчиваться оператором return, если только исполнение явно не может дойти до конца функции, например, если функция заканчивается вызовом panic или бесконечным циклом for без break.

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

func f(i, j, k, int, s, t string) { /*...*/ }

func f(i int, j int, k, int, s string, t string) { /*...*/ }

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

func add(x int, y int) int { return x + y }
func sub(x, y int) (z int) { z = x-y; return }
func first(x int, _ int) int { return x }
func zero(int, int) int { return 0 }

fmt.Printf("%T\n", add) // "func(int, int) int"
fmt.Printf("%T\n", sub) // "func(int, int) int"
fmt.Printf("%T\n", first) // "func(int, int) int"
fmt.Printf("%T\n", zero) // "func(int, int) int"

Тип функции иногда называют ее сигнатурой. Две функции имеют один и тот же тип, или сигнатуру, если они имеют одну и ту же последовательность типов и параметров и одну и ту же последовательность типов результатов. Имена параметров и результатов не влияют на тип функции, так же как не влияет то, было ли объявление функции факторизовано.

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

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

Аргументы передаются в функции по значению, поэтому функция получает копию каждого аргумента; изменения в копии не влияют на исходный объект. Однако, если аргумент содержит некоторую ссылку, как, например, указатель, срез, map, функцию или канал, то функция может влиять на объекты вызывающего кода с помощью косвенного внесения изменений с использованием аргумента-ссылки.

Иногда можно столкнуться с объявлением функции без тела, указывающим, что эта функция реализована на языке, отличном от языка Go. Такое объявление определяет сигнатуру функции.

func Sin(x float64) float64 // Реализована на ассемблере

Выводы:

  • Функции в Go определяются с помощью ключевого слова func, имени функции, списка параметров, списка результатов и тела функции;
    Пример объявления функции с двумя параметрами типа int и одним результатом типа int:
    func add(x int, y int) int {
      return x + y
    }
  • Список параметров функции содержит имена и типы параметров, которые являются локальными переменными функции и инициализируются значениями аргументов, переданными при вызове функции;
  • Список результатов функции указывает типы значений, возвращаемых функцией; если функция возвращает одно значение, скобки необязательны и опускаются;
  • Функции с именованными результатами автоматически инициализирует локальные переменные с соответствующими типами и начальными значениями; Пример функции с именованным результатом:
    func sum(x int, y int) (result int) {
      result = x + y
      return
    }
  • Аргументы функции передаются по значению, поэтому изменения аргументов внутри функции не влияют на исходные значения вызывающей стороны; однако, если аргумент содержит ссылку на объект (указатель, срез, map, функцию, канал), то функция может влиять на его состояние;
  • Тип функции определяется сигнатурой, состоящей из последовательности типов параметров и результатов; имена параметров и результатов не влияют на тип функции;
  • В Go отсутствуют параметры по умолчанию и передача аргументов по имени, что упрощает вызов функции и делает его более предсказуемым;
  • Возврат значений из функции осуществляется с помощью оператора return; если функция имеет список результатов, она должна заканчиваться оператором return, если только исполнение явно не может дойти до конца функции (например, из-за вызова panic или бесконечного цикла без break).