Как определить и вызвать функции в Go

Вступление

Function - это фрагмент кода, который после определения можно использовать повторно. Функции используются для того, чтобы облегчить понимание вашего кода, разбив его на небольшие понятные задачи, которые можно использовать более одного раза в вашей программе.

Go поставляется с мощной стандартной библиотекой, которая имеет много предопределенных функций. С пакетом fmt вы, вероятно, уже знакомы:

  • + fmt.Println () +, который выводит объекты на стандартный вывод (скорее всего, ваш терминал).

  • + fmt.Printf () +, который позволит вам отформатировать вывод на печать.

Имена функций включают круглые скобки и могут включать параметры.

В этом уроке мы рассмотрим, как определить свои собственные функции для использования в ваших проектах кодирования.

Определение функции

Давайте начнем с превращения классической программы https://www.digitalocean.com/community/tutorials/how-to-write-your-first-program-in-go[icHello, World! »В функцию.

Мы создадим новый текстовый файл в нашем текстовом редакторе и вызовем программу + hello.go +. Затем мы определим функцию.

Функция определяется с помощью ключевого слова + func +. Затем следует имя по вашему выбору и набор скобок, которые содержат любые параметры, которые примет функция (они могут быть пустыми). Строки кода функции заключены в фигурные скобки + {} +.

В этом случае мы определим функцию с именем + hello () +:

hello.go

func hello() {}

Это устанавливает начальный оператор для создания функции.

Отсюда мы добавим вторую строку, чтобы предоставить инструкции о том, что делает функция. В этом случае мы будем печатать + Hello, World! + На консоли:

hello.go

func hello() {
   fmt.Println("Hello, World!")
}

Наша функция теперь полностью определена, но если мы запустим программу на этом этапе, ничего не произойдет, так как мы не вызывали функцию.

Итак, внутри нашего функционального блока + main () + давайте вызовем функцию с помощью + hello () +:

hello.go

package main

import "fmt"

func main() {
   hello()
}

func hello() {
   fmt.Println("Hello, World!")
}

Теперь давайте запустим программу:

go run hello.go

Вы получите следующий вывод:

OutputHello, World!

Обратите внимание, что мы также ввели функцию с именем + main () +. Функция + main () + - это специальная функция, которая сообщает компилятору, что именно здесь программа должна * запуститься *. Для любой программы, которой вы хотите быть executable (программа, которую можно запустить из командной строки), вам понадобится функция + main () +. Функция + main () + должна появляться только один раз, находиться в + main () + package, получать и не возвращать аргументы. Это позволяет выполнять program в любой программе Go. Согласно следующему примеру:

main.go

package main

import "fmt"

func main() {
   fmt.Println("this is the main section of the program")
}

Функции могут быть более сложными, чем определенная нами функция + hello () +. Мы можем использовать https://www.digitalocean.com/community/tutorials/how-to-construct-for-loops-in-go [+ for + loops], https://www.digitalocean.com/community/ учебные пособия / как написать условные операторы в условных выражениях и многое другое в нашем функциональном блоке.

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

names.go

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 + как две отдельные функции.

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

Работа с параметрами

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

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

Давайте создадим программу, которая повторяет слово определенное количество раз. Для повторения слова потребуется параметр + string с именем` + word n` и параметр + int с именем` + reps`.

repeat.go

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 +. Мы создадим функцию, которая добавляет параметры вместе в разных конфигурациях. Их суммы будут напечатаны функцией. Затем мы вызовем функцию и передадим числа в функцию.

add_numbers.go

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 +:

double.go

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:

double.go

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 +, даже если они не находятся в конце функции:

return_loop.go

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 +. Поскольку мы находимся в функции + loop Five, и` + return` в любой точке функции выйдет из функции. В результате мы никогда не доберемся до последней строки в этой функции, чтобы напечатать оператор + Эта строка не будет выполняться. +.

Использование оператора + return внутри цикла` + for` завершает функцию, поэтому строка, находящаяся вне цикла, не будет выполняться. Если бы вместо этого мы использовали https://www.digitalocean.com/community/tutorials/how-to-use-break-and-continue-statements-when-working-with-loops-in-go#break- оператор [+ break + оператор], в это время мог бы выйти только цикл, и запустилась бы последняя строка + fmt.Println () +.

Оператор + return + выходит из функции и может возвращать значение, если оно указано в сигнатуре функции.

Возврат нескольких значений

Для функции может быть указано более одного возвращаемого значения. Давайте рассмотрим программу + repeat.go + и сделаем так, чтобы она возвращала два значения. Первое будет повторным значением, а второе будет ошибкой, если параметр + reps + не является значением больше, чем + 0 +:

repeat.go

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 .