Your first function
A cookbook describes a sauce once, on a page of its own. The other recipes do not repeat its steps; they say briefly: "make the sauce". Your own function in a program works the same way: its steps are written in one place, and you can call it from anywhere.
When the same calculation is needed in several places in a program, it is written once—in a separate function. The function add takes two integers and returns their sum:
package main
import "fmt"
func add(a, b int) int {
return a + b
}
func main() {
fmt.Println(add(2, 3)) // 5
fmt.Println(add(10, -4)) // 6
}Let's follow the first call:
add(2, 3)sends execution into the functionadd, whereais2andbis3.- The line
return a + bcomputes5and returns that number to the place the function was called from. fmt.Printlngets5and prints it.
The second call works the same way with other numbers and prints 6.
Press "Next step" and watch control leave main for add and come back with a ready number.
1–4package main · import "fmt"5func add(a, b int) int {6 return a + b7}8 9func main() {10 fmt.Println(add(2, 3))11 fmt.Println(add(10, -4))12}
To print the result, main first calls add(2, 3).
Declaring a function
The line func add(a, b int) int reads left to right:
funcis the keyword: "I'm declaring a function";addis the function's name;(a, b int)are the parameters, variables that receive values when the function is called; both have the typeint, that is, an integer;intafter the parentheses is the function's result type.
The return statement ends the function and returns the value of the expression after it. An expression is code that produces a value, such as a + b.
A function can be declared above or below main. The compiler reads the whole package, so the order of declarations in the file does not matter.
The call and its arguments
In the call add(2, 3), the numbers 2 and 3 are the arguments. Here is what happens to them and to the call itself:
- the arguments go into the parameters in order:
2intoa,3intob; - the call is replaced by the value the function returned, so you can pass it to
fmt.Println; - the number of arguments must match the number of parameters: the compiler rejects
add(1)withnot enough arguments in call to add.
Here the sauce picture stops working. A sauce made by the recipe comes out the same every time. A function, though, gets its own arguments on every call, and its result depends on them.
Order of evaluation
One expression can hold several operators and calls. Let's look at three lines:
fmt.Println(1 + 2*3) // 7
fmt.Println((1 + 2) * 3) // 9
fmt.Println(add(add(1, 2), 3)) // 6The first two lines follow the rules for operators, and the third follows the rule for nested calls. Let's take both rules apart.
Operators
The operators +, - and * work with integers. These rules set their order:
- as in math,
*is evaluated before+and-; - parentheses change that order;
- spaces do not affect the order:
1 + 2*3and1+2 * 3give the same result.
Writing 2*3 without spaces only hints to the reader that the multiplication runs first. By these rules, the first two lines of the example are computed like this:
1 + 2*3:2*3runs first, and1 + 6gives7.(1 + 2) * 3: the parentheses make1 + 2run first, and3 * 3gives9.
Nested calls
A function call can also be an argument of another call. Then the inner call runs first, and its result becomes the argument of the outer one.
In the third line of the example, it goes like this:
add(1, 2)returns3.add(3, 3)returns6.fmt.Printlnprints only6.
Common mistake
The function prints the sum instead of returning it, and it has no result type:
package main
import "fmt"
func add(a, b int) {
fmt.Println(a + b)
}
func main() {
fmt.Println(add(2, 3)) // ✗
}add(2, 3) (no value) used as valueA function without a result type returns nothing, so its call cannot be passed to fmt.Println. The fix is to put int after the parentheses and return the sum with return, as in the first example.
Key points
- Parameters with their types go in the parentheses after the function name, and the result type goes after the parentheses.
returnends the function, and the call is replaced by the value it returned.*runs before+and-, and an inner call runs before the outer one.- A function without a result type returns nothing, and its call cannot be passed to
fmt.Println.
Subscribe to take the course
The course is free. Sign in with Telegram and subscribe to the channel to open every lesson.