preface
This blog post mainly introduces the function definition of Go language and its usage.
Declaring and using functions
In Go language, the format of function declaration is as follows:
func function_name([parameter list])[return_types]{ //Function body }
When you use the compiler for development, such as GoLand, you will find that if you enter func, the enter structure will appear automatically. This is also a very convenient place for Go language development. Next, the author will explain the above parameters in detail:
- func: function declaration keyword
- function_name: function name
- Parameter: parameter list; optional; no parameter is allowed
- return_types: return value type, which is also optional
Next, let's give an example to illustrate the use. The example is as follows (output 3):
func main() { fmt.Println(XaddY(1, 2)) } func XaddY(x, y int) int { return x + y }
Return multiple values
In Go language functions, if you need to return multiple values, you don't need to return them through a list or array. You can return any number of values separately. This is also a very convenient place for Go language. Examples are as follows:
func main() { fmt.Println(XaddYOrXmultiplyY(1, 2)) } func XaddYOrXmultiplyY(x, y int) (int,int) { return x + y, x * y }
Here, we return two parameters, one is the addition value and the other is the multiplication value.
return can be empty
When a Go language function has a return value, its return can be empty, but it is not that there is no return value, but the order of the return value can be directly defined in the function definition.
Next, we will modify the above returned multiple values. The example is as follows:
func main() { fmt.Println(XaddYOrXmultiplyY(1, 2)) } func XaddYOrXmultiplyY(x, y int) (a, b int) { a = x + y b = x * y return }
Here, the data of the return value is still the same as the above return value. Because the author has defined the return order of the return value into the return parameter, return can be empty.
If you write your own return statement, you can also modify the order, such as return b,a. It will return b first and then a. You can define the return order according to the return order of the parameter, that is, you can return the correct number according to the return order.
Function parameters
parameter
In Go language, parameters are also divided into real participation formal parameters. What are real participation parameters?
- Argument: when calling a function, the actual data passed to the formal parameter is called the actual parameter.
- Formal parameter: when calling a function, the data used to receive external incoming data is called formal parameter.
pass by value
Value passing means that a copy of the actual parameters is passed to the function when calling the function. In this way, the modification in the function will not have any impact on the passed parameters.
For example, we implement a function of exchanging values to see the effect:
func main() { var x,y int=5,9 exchange(x,y) fmt.Println(x,y) } func exchange(x, y int){ var temp int temp=x x=y y=temp }
After running, you will find that the console still has no change in the values of 5, 9, x and y. This is the structure of value transfer and will not change the original variable value.
Reference passing
When passed by reference, the original variable will be changed. Similarly, we still use it to realize data exchange. Examples are as follows:
func main() { var x, y int = 5, 9 exchange(&x, &y) fmt.Println(x, y) } func exchange(x, y *int) { var temp int temp = *x *x = *y *y = temp }
At this time, when you run again, the console will output 9 and 5. Because it is passed by reference, the original parameter value is changed.
Optional function
As the name suggests, it is a parameter that can be required or not, and can be long or short. Examples of defining optional functions are as follows:
func main() { var x = []int{2, 3} fmt.Println(x) } func exchange(arg ...int) { var temp int temp = arg[0] arg[0] = arg[1] arg[1] = temp }
Note that arg is a slice of int, which can be traversed directly through for range.
Anonymous function
Anonymous functions are called "closures", which refer to a class of functions or subroutines without defined identifiers (function names). Anonymous function has no function name, only function body. Function can be used as a variable assigned to function type; Anonymous functions are often passed as variables.
Definition of anonymous function
The definition of anonymous function can be understood as a function without a name. Its definition and usage are as follows:
//definition func (parameter list)(Return value list){ //Function body } //Mode of use func main() { x, y := 3, 9 defer func(a int) { fmt.Println(a, y) //y is a closure reference }(x) x += 10 y += 100 fmt.Println(x, y) }
After operation, the output is as follows:
Running the above code, readers will surely find that the last output statement is printed first, and then func output is printed, because defer is a deferred statement. The defer design is designed to release resources in time after the function is executed. (explain separately at last)
Moreover, the anonymous function above is an "inline" statement. The advantage of anonymous function is that it can directly use the variables in the function without declaration.
Call of anonymous function
Next, we assign an anonymous function to a variable and use the function as a variable. Examples are as follows:
func main() { x, y := 3, 9 f := func(x, y int) { fmt.Println(x + y) } f(x, y) }
Callback function
The Callback function, i.e. Callback, will return to the main function after being called by the main function. That is, a reference to a piece of executable code passed to other code through function parameters.
Anonymous functions are used as callback functions, which are very common in Go language. For example, you can use an anonymous function as a parameter to traverse the elements in the slice. An example is as follows:
func TraversalPrint(list []int, f func(int)) { for _, value := range list { f(value) } } func main() { slice := []int{1, 2, 3, 4, 5} TraversalPrint(slice, func(value int) { fmt.Println(value) }) }
After running, the effect is as follows:
defer deferred statement
Earlier, we briefly introduced defer. It is designed to release resources in time after the function is executed. The specific logic is as follows:
- When the program executes a defer, it will not execute the statement after defer immediately, but press the statement after defer into a stack specially storing defer statements, and then continue to execute the next statement of the function.
- After the function is executed, the statements are taken out from the top of the stack in turn from the defer stack for execution (the rule of the stack is first in and last out, that is, the first in and last executed)
- When defer puts the statement on the stack, the relevant values will also be copied into the stack. Therefore, a above outputs the initial value of x.
Examples are as follows:
func deferCall() { defer func1() defer func2() defer func3() } func func1() { fmt.Println("1") } func func2() { fmt.Println("2") } func func3() { fmt.Println("3") } func main() { deferCall() }
After running, you will find that it will output 3, 2 and 1, which is the first in and last out of the stack.
Execution order of defer and return
If there is a defer and a return value in a function body, what is its order? Next, let's observe through a piece of code. The example is as follows:
var name string="liyuanjing" func func1() string { defer func() { name="fengxinyao" }() fmt.Println(name) return name } func main() { func1 :=func1() fmt.Println(name) fmt.Println(func1) }
After running, the effect is as follows:
Analysis of operation results:
- In the main() function, the function is only assigned to a variable at the beginning, and no function is specified, so the original name value "liyunajing" must be output for the first time.
- After calling the function, the global variable is changed in defer, and the value of name has changed to "fengxinyao".
- Then why is the final output still "liyuanjing"? Explain that there is only one, that is, defer is called after return. Therefore, func1 has been assigned "liyuanjing" before defer is executed.
defer common scenarios
In addition to releasing resources, defer has another application scenario, which is to be used together with the recover() function.
When a program goes down or encounters panic errors, the recover() function can resume execution without reporting downtime errors. As I said before, defer can not only be invoked before return returns, but also can be executed before downtime of the program when the program shows panic error.