Функция — это часть кода, которая после определения может многократно использоваться. Функции используются для упрощения понимания кода путем разделения его на небольшие понятные задачи, которые могут использоваться многократно в вашей программе.
Go поставляется с мощной стандартной библиотекой, где имеются самые разные предопределенные функции. С некоторыми из них вы уже знакомы, например с функциями пакета fmt:
fmt.Println()
, которая будет выводить объекты в стандартный вывод (скорее всего, это будет ваш терминал).fmt.Printf()
, которая позволяет форматировать отображаемый результат.Имена функций включают скобки и могут содержать параметры.
В этом обучающем руководстве мы узнаем, как определить ваши собственные функции для вашего проекта.
Давайте начнем с превращения классического примера “Hello, World!” из программы в функцию.
Мы создадим новый текстовый файл в текстовом редакторе по выбору и вызовем программу hello.go
. Затем мы определим функцию.
Функция определяется с помощью ключевого слова func
. За ним следует имя функции и набор скобок, которые хранят любые параметры, принимаемые функцией (скобки могут быть пустыми). Строки кода функции помещаются в фигурные скобки {}
.
В данном случае мы определим функцию с именем hello()
:
func hello() {}
Это первоначальное объявление для создания функции.
Теперь мы можем добавить вторую строку для определения того, что будет делать наша функция. В данном случае мы будем выполнять вывод Hello, World!
в консоль:
func hello() {
fmt.Println("Hello, World!")
}
Теперь наша функция полностью определена, но если мы запустим программу в данный момент, ничего не произойдет, поскольку мы не вызывали функцию.
Давайте внутри нашего блока функции main()
вызовем функцию с именем hello()
:
package main
import "fmt"
func main() {
hello()
}
func hello() {
fmt.Println("Hello, World!")
}
Теперь мы запустим программу:
- go run hello.go
Вывод должен выглядеть следующим образом:
OutputHello, World!
Обратите внимание, что мы также ввели функцию main()
. Функция main()
— это особая функция, которая указывает компилятору, что это место, откуда должно начинаться выполнение программы. Для любой программы, которая будет исполняемой (программа, которая может запускаться из командной строки), вам потребуется функция main()
. Функция main()
должна использоваться только один раз и находиться в пакете main()
, она не имеет аргументов и возвращаемого значения. Это позволяет реализовать исполнение в любой программе Go. Как показано в следующем примере:
package main
import "fmt"
func main() {
fmt.Println("this is the main section of the program")
}
Функции могут быть более сложными, чем функция hello()
, которую мы определили. Мы можем использовать циклы for
, условные операторы и многое другое внутри нашей функции.
Например, следующая функция использует условный оператор для проверки того, содержит ли переменная name
гласные звуки, а затем использует цикл for
для прохождения по буквам строки name
.
package main
import (
"fmt"
"strings"
)
func main() {
names()
}
func names() {
fmt.Println("Enter your name:")
var name string
fmt.Scanln(&name)
// Check whether name has a vowel
for _, v := range strings.ToLower(name) {
if v == 'a' || v == 'e' || v == 'i' || v == 'o' || v == 'u' {
fmt.Println("Your name contains a vowel.")
return
}
}
fmt.Println("Your name does not contain a vowel.")
}
Функция names()
, которую мы определили здесь, устанавливает значение переменной name
, а затем задает условный оператор внутри цикла for
. Здесь показано, как можно организовывать код внутри функции. Однако в зависимости от того, что мы намерены делать в нашей программе и как мы хотим организовать наш код, мы можем использовать условный оператор и цикл for
в качестве двух отдельных функций.
Определение функций внутри программы делает наш код модульным и подходящим для многократного использования, чтобы мы могли вызывать одни и те же функции без необходимости перезаписи.
До настоящего момента мы изучали функции с пустыми скобками, которые не имеют аргументов, но мы можем определить параметры в определении функций внутри скобок.
Параметр — это именованная сущность в определении функции, указывающая аргумент, который может принимать функция. В Go вы должны указывать тип данных для каждого параметра.
Давайте создадим программу, которая повторяет слово определенное количество раз. Она будет получать параметр string
с именем word
и параметр int
с именем reps
для количества повторений этого слова.
package main
import "fmt"
func main() {
repeat("Sammy", 5)
}
func repeat(word string, reps int) {
for i := 0; i < reps; i++ {
fmt.Print(word)
}
}
Мы передали значение Sammy
для параметра word
и 5
для параметра reps
. Эти значения соответствуют каждому параметру в заданном нами порядке. Функция repeat
имеет цикл for
, который будет выполняться количество раз, определенное значением параметра reps
. Для каждой итерации значение параметра word
выводится на экран.
Здесь вы увидите вывод программы:
OutputSammySammySammySammySammy
Если у вас есть набор параметров, которые имеют одинаковое значение, вы можете каждый раз не указывать тип значения. Давайте создадим небольшую программу, которая получает параметры x
, y
и z
, имеющие тип int
. Мы создадим функцию, которая складывает значения параметров в разных конфигурациях. Получаемые суммы будут выводиться функцией. Затем мы будем вызывать функцию и передавать числа в эту функцию.
package main
import "fmt"
func main() {
addNumbers(1, 2, 3)
}
func addNumbers(x, y, z int) {
a := x + y
b := x + z
c := y + z
fmt.Println(a, b, c)
}
Когда мы создали сигнатуру функции для addNumbers
, не нужно было указывать тип каждый раз, а только в конце.
Мы передали число 1
в параметр x
, 2
в параметр y
и 3
в параметр z
. Эти значения соответствуют каждому параметру в заданном нами порядке.
Программа выполняет следующие математические операции со значениями, которые мы передавали в параметрах:
a = 1 + 2
b = 1 + 3
c = 2 + 3
Функция также выводит a
, b
и c
, и на основе этих математических операций мы ожидаем, что a
будет равна 3
, b
— 4
и c
— 5
. Давайте запустим программу:
- go run add_numbers.go
Output3 4 5
Когда мы передадим 1
, 2
и 3
в качестве параметров функции addNumbers()
, мы получаем ожидаемый результат.
Параметры — это аргументы, обычно определяемые как переменные внутри определений функций. Им могут присваиваться значения, когда вы запускаете метод, передавая аргументы в функцию.
Вы можете передать значение параметра в функцию, а функция может также генерировать значение.
Функция может генерировать значение с помощью оператора return
, которые завершает работу функции и опционально передает выражение обратно вызывающей сущности. Тип возвращаемых данных также обязательно должен быть указан.
До настоящего момента мы использовали fmt.Println()
вместо оператора return
в наших функциях. Давайте создадим программу, которая вместо вывода на экран будет возвращать переменную.
В новом текстовом файле с именем double.go
мы создадим программу, которая удваивает параметр x
и возвращает переменную y
. Мы осуществляем вызов для вывода переменной result
, которая создается при запуске функции double()
с переданным ей значением 3
:
package main
import "fmt"
func main() {
result := double(3)
fmt.Println(result)
}
func double(x int) int {
y := x * 2
return y
}
Мы можем запустить программу и увидеть следующий вывод:
- go run double.go
Output6
Целое число 6
возвращается как результат, что является ожидаемым значением при умножении 3
на 2
.
Если для функции определено возвращаемое значение, вы должны указать в коде оператор return. В обратном случае вы получите ошибку компилятора.
Мы можем продемонстрировать это, закомментировав строку с оператором return:
package main
import "fmt"
func main() {
result := double(3)
fmt.Println(result)
}
func double(x int) int {
y := x * 2
// return y
}
Теперь мы снова запустим программу:
- go run double.go
Output./double.go:13:1: missing return at end of function
Без оператора return
программу не удастся скомпилировать.
Выполнение функции прекращается немедленно при достижении оператора return
, даже если он находится не в конце функции:
package main
import "fmt"
func main() {
loopFive()
}
func loopFive() {
for i := 0; i < 25; i++ {
fmt.Print(i)
if i == 5 {
// Stop function at i == 5
return
}
}
fmt.Println("This line will not execute.")
}
Здесь мы используем цикл for
и выполняем 25
итераций данного цикла. Однако внутри цикла for
у нас есть условный оператор if
, который проверяет, имеет ли i
значение 5
. Если условие выполняется, выполняется оператор return
. Поскольку мы находимся внутри функции loopFive
, срабатывание оператора return
внутри этой функции приводит к прекращению ее работы. В результате мы никогда не доберемся до последней строки, которая выводит строку This line will not execute
.
Использование оператора return
внутри цикла for
позволяет завершить работу функции, так что строка, находящаяся вне цикла, не будет выполняться. Если же, напротив, мы бы использовали оператор break
, прекращалась только работа цикла, а последняя строка fmt.Println()
все равно бы выполнялась.
Оператор return
прекращает работу функции и может возвращать значение, если оно указано в сигнатуре функции.
Для функции может быть указано более одного возвращаемого значения. Давайте посмотрим на программу repeat.go
и сделаем так, чтобы она возвращала два значения. Первым значением будет повторяющееся значение, а второе будет ошибкой, которая возникает, если параметр reps
имеет значение меньше 0
:
package main
import "fmt"
func main() {
val, err := repeat("Sammy", -1)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(val)
}
func repeat(word string, reps int) (string, error) {
if reps <= 0 {
return "", fmt.Errorf("invalid value of %d provided for reps. value must be greater than 0.", reps)
}
var value string
for i := 0; i < reps; i++ {
value = value + word
}
return value, nil
}
Первое, что делает функция repeat
, — это проверка действительности значения аргумента reps
. Любое значение меньше 0
будет вызывать ошибку. После того как мы передали значение -1
, эта часть кода будет выполнена. Обратите внимание, что при выполнении возврата из функции, мы должны предоставить возвращаемые значения типа string
и error
. Поскольку предоставленные аргументы привели к ошибке, мы передадим пустую строку для первого возвращаемого значения и ошибку для второго возвращаемого значения.
В функции main()
мы можем получить оба возвращаемых значения, объявив две новые переменные, value
и err
. Поскольку в возвращаемом значении может быть ошибка, нам нужно проверить, получаем ли мы ошибку, прежде чем продолжить работу с нашей программой. В данном примере мы получили ошибку. Мы выводим ошибку и с помощью return
выходим из функции main()
для выхода из программы.
Если ошибки не было, мы выводим возвращаемое значение функции.
Примечание. Рекомендуется возвращать только два или три значения. Кроме того, вы всегда должны возвращать все ошибки в качестве последнего возвращаемого значения функции.
При запуске программы вы получите следующий вывод:
Outputinvalid value of -1 provided for reps. value must be greater than 0.
В этом разделе мы изучили, как использовать оператор return
для возвращения функцией нескольких значений.
Функции — это блоки кода с инструкциями, которые выполняются внутри программы и помогают сделать код модульным и доступным для многоразового использования.
Чтобы узнать больше о том, как сделать ваш код более модульным, вы можете ознакомиться с нашим руководством Написание пакетов в Go.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!