介绍 (Introduction)
A function is a section of code that, once defined, can be reused. Functions are used to make your code easier to understand by breaking it into small, understandable tasks that can be used more than once throughout your program.
函数是一段代码,一旦定义,便可以重用。 通过将函数分解为可理解的细小任务,这些函数可在整个程序中多次使用,这些函数使代码更易于理解。
Go ships with a powerful standard library that has many predefined functions. Ones that you are probably already familiar with from the fmt package are:
Go附带了功能强大的标准库,该库具有许多预定义功能。 您可能已经从fmt包中熟悉的是:
fmt.Println()
which will print objects to standard out (most likely your terminal).
fmt.Println()
会将对象打印为标准输出(很可能是您的终端)。
fmt.Printf()
which will allow you to format your printed output.
fmt.Printf()
它将允许您格式化打印输出。
Function names include parentheses and may include parameters.
函数名称包含括号,并且可以包含参数。
In this tutorial, we’ll go over how to define your own functions to use in your coding projects.
在本教程中,我们将介绍如何定义自己的函数以在编码项目中使用。
定义功能 (Defining a Function)
Let’s start with turning the classic “Hello, World!” program into a function.
让我们从经典的“ Hello,World!”开始 程序变成一个函数。
We’ll create a new text file in our text editor of choice, and call the program hello.go
. Then, we’ll define the function.
我们将在所选的文本编辑器中创建一个新的文本文件,然后调用程序hello.go
。 然后,我们将定义函数。
A function is defined by using the func
keyword. This is then followed by a name of your choosing and a set of parentheses that hold any parameters the function will take (they can be empty). The lines of function code are enclosed in curly brackets {}
.
通过使用func
关键字定义func
。 然后是您选择的名称和一组括号,这些括号包含函数将采用的所有参数(它们可以为空)。 功能代码行括在大括号{}
。
In this case, we’ll define a function named hello()
:
在这种情况下,我们将定义一个名为hello()
的函数:
hello.go
你好
func hello() {}
This sets up the initial statement for creating a function.
这将建立用于创建函数的初始语句。
From here, we’ll add a second line to provide the instructions for what the function does. In this case, we’ll be printing Hello, World!
to the console:
从这里开始,我们将添加第二行以提供有关该功能的说明。 在这种情况下,我们将打印Hello, World!
到控制台:
hello.go
你好
func hello() {
fmt.Println("Hello, World!")
}
Our function is now fully defined, but if we run the program at this point, nothing will happen since we didn’t call the function.
现在已经完全定义了函数,但是如果此时运行程序,则由于未调用函数,因此不会发生任何事情。
So, inside of our main()
function block, let’s call the function with hello()
:
因此,在我们的main()
函数块中,让我们使用hello()
调用该函数:
hello.go
你好
package main
import "fmt"
func main() {
hello()
}
func hello() {
fmt.Println("Hello, World!")
}
Now, let’s run the program:
现在,让我们运行程序:
- go run hello.go 去跑hello.go
You’ll receive the following output:
您将收到以下输出:
Output
Hello, World!
Notice that we also introduced a function called main()
. The main()
function is a special function that tells the compiler that this is where the program should start. For any program that you want to be executable (a program that can be run from the command line), you will need a main()
function. The main()
function must appear only once, be in the main()
package, and receive and return no arguments. This allows for program execution in any Go program. As per the following example:
注意,我们还引入了一个称为main()
的函数。 main()
函数是一个特殊的函数,它告诉编译器这是程序应该从哪里开始的 。 对于您要可执行的任何程序(可以从命令行运行的程序),您将需要main()
函数。 main()
函数必须仅出现一次,在main()
包中 ,并且不接收和返回任何参数。 这允许在任何Go程序中执行程序。 按照以下示例:
main.go
main.go
package main
import "fmt"
func main() {
fmt.Println("this is the main section of the program")
}
Functions can be more complicated than the hello()
function we defined. We can use for
loops, conditional statements, and more within our function block.
函数可能比我们定义的hello()
函数复杂。 我们可以在功能块中使用for
循环 , 条件语句等。
For example, the following function uses a conditional statement to check if the input for the name
variable contains a vowel, then uses a for
loop to iterate over the letters in the name
string.
例如,以下函数使用条件语句来检查name
变量的输入是否包含元音,然后使用for
循环遍历name
字符串中的字母。
names.go
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.")
}
The names()
function we define here sets up a name
variable with input, and then sets up a conditional statement within a for
loop. This shows how code can be organized within a function definition. However, depending on what we intend with our program and how we want to set up our code, we may want to define the conditional statement and the for
loop as two separate functions.
我们在此处定义的names()
函数使用输入设置name
变量,然后在for
循环中设置条件语句。 这显示了如何在函数定义中组织代码。 但是,根据我们对程序的期望以及如何设置代码,我们可能希望将条件语句和for
循环定义为两个单独的函数。
Defining functions within a program makes our code modular and reusable so that we can call the same functions without rewriting them.
在程序中定义函数使我们的代码模块化和可重用,以便我们可以调用相同的函数而无需重写它们。
使用参数 (Working with Parameters)
So far we have looked at functions with empty parentheses that do not take arguments, but we can define parameters in function definitions within their parentheses.
到目前为止,我们已经研究了带有不带参数的空括号的函数,但是我们可以在函数定义中的括号内定义参数。
A parameter is a named entity in a function definition, specifying an argument that the function can accept. In Go, you must specify the data type for each parameter.
参数是函数定义中的命名实体,它指定函数可以接受的参数。 在Go中,您必须为每个参数指定数据类型 。
Let’s create a program that repeats a word a specified number of times. It will take a string
parameter called word
and an int
parameter called reps
for the number of times to repeat the word.
让我们创建一个程序,该程序将单词重复指定的次数。 重复单词的次数将包含一个名为word
的string
参数和一个名为reps
的int
参数。
repeat.go
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)
}
}
We passed the value Sammy
in for the word
parameter, and 5
for the reps
parameter. These values correspond with each parameter in the order they were given. The repeat
function has a for
loop that will iterate the number of times specified by the reps
parameter. For each iteration, the value of the word
parameter is printed.
我们通过价值Sammy
中的word
参数,以及5
为reps
的参数。 这些值按照给定的顺序与每个参数相对应。 repeat
函数具有一个for
循环,该循环将迭代reps
参数指定的reps
。 对于每次迭代,都会打印word
参数的值。
Here is the output of the program:
这是程序的输出:
Output
SammySammySammySammySammy
If you have a set of parameters that are all the same value, you can omit specifying the type each time. Let’s create a small program that takes in parameters x
, y
, and z
that are all int
values. We’ll create a function that adds the parameters together in different configurations. The sums of these will be printed by the function. Then we’ll call the function and pass numbers into the function.
如果一组参数都具有相同的值,则可以每次省略指定类型。 让我们创建一个小程序,该程序接受所有均为int
值的参数x
, y
和z
。 我们将创建一个将参数添加到不同配置中的函数。 这些的总和将由函数打印。 然后,我们将调用该函数并将数字传递给该函数。
add_numbers.go
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)
}
When we created the function signature for addNumbers
, we did not need to specify the type each time, but only at the end.
当我们为addNumbers
创建函数签名时,我们不需要每次都指定类型,而只需在最后指定类型。
We passed the number 1
in for the x
parameter, 2
in for the y
parameter, and 3
in for the z
parameter. These values correspond with each parameter in the order they are given.
我们为x
参数传递了数字1
in,为y
参数传递了2
in,为z
参数传递了3
in。 这些值按照给定的顺序与每个参数相对应。
The program is doing the following math based on the values we passed to the parameters:
该程序基于我们传递给参数的值进行以下数学运算:
a = 1 + 2
b = 1 + 3
c = 2 + 3
The function also prints a
, b
, and c
, and based on this math we would expect a
to be equal to 3
, b
to be 4
, and c
to be 5
. Let’s run the program:
该函数还会打印a
, b
和c
,并且根据此数学公式,我们希望a
等于3
, b
等于4
, c
等于5
。 让我们运行程序:
- go run add_numbers.go 去运行add_numbers.go
Output
3 4 5
When we pass 1
, 2
, and 3
as parameters to the addNumbers()
function, we receive the expected output.
当我们通过1
, 2
,和3
作为参数传递给addNumbers()
函数中,我们得到预期的输出。
Parameters are arguments that are typically defined as variables within function definitions. They can be assigned values when you run the method, passing the arguments into the function.
参数是通常在函数定义中定义为变量的参数。 在您运行方法时,可以为它们分配值,并将参数传递给函数。
返回值 (Returning a Value)
You can pass a parameter value into a function, and a function can also produce a value.
您可以将参数值传递给函数,函数也可以产生值。
A function can produce a value with the return
statement, which will exit a function and optionally pass an expression back to the caller. The return data type must be specified as well.
函数可以使用return
语句产生一个值,该值将退出函数并有选择地将表达式传递回调用方。 还必须指定返回数据类型。
So far, we have used the fmt.Println()
statement instead of the return
statement in our functions. Let’s create a program that instead of printing will return a variable.
到目前为止,我们已经在fmt.Println()
使用了fmt.Println()
语句而不是return
语句。 让我们创建一个程序,而不是打印它将返回一个变量。
In a new text file called double.go
, we’ll create a program that doubles the parameter x
and returns the variable y
. We issue a call to print the result
variable, which is formed by running the double()
function with 3
passed into it:
在一个名为double.go
的新文本文件中,我们将创建一个程序,该程序将参数x
加倍并返回变量y
。 我们发出调用以打印result
变量,该result
是通过运行double()
函数并传递3
形成的:
double.go
double.go
package main
import "fmt"
func main() {
result := double(3)
fmt.Println(result)
}
func double(x int) int {
y := x * 2
return y
}
We can run the program and see the output:
我们可以运行程序并查看输出:
- go run double.go 去跑double.go
Output
6
The integer 6
is returned as output, which is what we would expect by multiplying 3
by 2
.
整数6
作为输出返回,这是我们将3
乘以2
。
If a function specifies a return, you must provide a return as part of the code. If you do not, you will receive a compilation error.
如果函数指定了返回值,则必须在代码中提供返回值。 否则,您将收到编译错误。
We can demonstrate this by commenting out the line with the return statement:
我们可以通过用return语句注释掉这一行来证明这一点:
double.go
double.go
package main
import "fmt"
func main() {
result := double(3)
fmt.Println(result)
}
func double(x int) int {
y := x * 2
// return y
}
Now, let’s run the program again:
现在,让我们再次运行该程序:
- go run double.go 去跑double.go
Output
./double.go:13:1: missing return at end of function
Without using the return
statement here, the program cannot compile.
如果不使用return
语句,程序将无法编译。
Functions exit immediately when they hit a return
statement, even if they are not at the end of the function:
即使它们不在函数末尾,它们也会在return
语句时立即退出:
return_loop.go
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.")
}
Here we iterate through a for
loop, and tell the loop to run 25
iterations. However, inside the for
loop, we have a conditional if
statement that checks to see if the value of i
is equal to 5
. If it is, we issue a return
statement. Because we are in the loopFive
function, any return
at any point in the function will exit the function. As a result, we never get to the last line in this function to print the statement This line will not execute.
.
在这里,我们遍历一个for
循环,并告诉该循环运行25
次迭代。 但是,在for
循环中,我们有一个条件if
语句,用于检查i
的值是否等于5
。 如果是这样,我们将发布return
声明。 因为我们在loopFive
函数中, loopFive
函数中任何点的任何return
都将退出该函数。 结果,我们永远不会到达此函数的最后一行以打印该语句。 This line will not execute.
。
Using the return
statement within the for
loop ends the function, so the line that is outside of the loop will not run. If, instead, we had used a break
statement, only the loop would have exited at that time, and the last fmt.Println()
line would run.
在for
循环内使用return
语句会终止该函数,因此循环外的行将不会运行。 相反,如果我们使用了break
语句 ,那么到那时只有循环会退出,最后的fmt.Println()
行将运行。
The return
statement exits a function, and may return a value if specified in the function signature.
return
语句退出一个函数,并且如果在函数签名中指定,则可以返回一个值。
返回多个值 (Returning Multiple Values)
More than one return value can be specified for a function. Let’s examine the repeat.go
program and make it return two values. The first will be the repeated value and the second will be an error if the reps
parameter is not a value greater than 0
:
一个函数可以指定多个返回值。 让我们检查repeat.go
程序并使它返回两个值。 如果reps
参数的值不大于0
,则第一个将是重复值,第二个将是错误:
repeat.go
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
}
The first thing the repeat
function does is check to see if the reps
argument is a valid value. Any value that is not greater than 0
will cause an error. Since we passed in the value of -1
, this branch of code will execute. Notice that when we return from the function, we have to provide both the string
and error
return values. Because the provided arguments resulted in an error, we will pass back a blank string for the first return value, and the error for the second return value.
repeat
功能要做的第一件事是检查reps
参数是否为有效值。 任何不大于0
值都将导致错误。 由于我们传入的值为-1
,因此该代码分支将执行。 注意,当我们从函数返回时,我们必须提供string
和error
返回值。 因为提供的参数导致错误,所以我们将为第一个返回值传回空白字符串,并为第二个返回值传回错误。
In the main()
function, we can receive both return values by declaring two new variables, value
and err
. Because there could be an error in the return, we want to check to see if we received an error before continuing on with our program. In this example, we did receive an error. We print out the error and return
out of the main()
function to exit the program.
在main()
函数中,我们可以通过声明两个新变量value
和err
来接收两个返回值。 由于返回中可能存在错误,因此我们希望在继续执行程序之前检查是否收到错误。 在这个例子中,我们确实收到了一个错误。 我们打印出错误并return
该出main()
函数退出程序。
If there was not an error, we would print out the return value of the function.
如果没有错误,我们将打印出函数的返回值。
Note: It is considered best practice to only return two or three values. Additionally, you should always return all errors as the last return value from a function.
注意:最佳做法是仅返回两个或三个值。 此外,您应始终将所有错误作为函数的最后一个返回值返回。
Running the program will result in the following output:
运行该程序将得到以下输出:
Output
invalid value of -1 provided for reps. value must be greater than 0.
In this section we reviewed how we can use the return
statement to return multiple values from a function.
在本节中,我们回顾了如何使用return
语句从一个函数返回多个值。
结论 (Conclusion)
Functions are code blocks of instructions that perform actions within a program, helping to make our code reusable and modular.
函数是在程序中执行操作的指令代码块,有助于使我们的代码可重用和模块化。
To learn more about how to make your code more modular, you can read our guide on How To Write Packages in Go.
要了解有关如何使代码更具模块化的更多信息,可以阅读有关如何在Go中编写包的指南。
翻译自: https://www.digitalocean.com/community/tutorials/how-to-define-and-call-functions-in-go