Объявление функции имеет имя, список параметров, необязательный список результатов и тело:
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
).