Why functions take input
A function without input does the same thing on every call. Most of the time you want the result to depend on a value, such as printing Welcome, Andy! for one user and Welcome, John! for another. Parameters make that possible: they let a function accept values from the code that calls it.
Parameters in Go
A parameter is a variable declared in the parentheses of the function header. In Go, every parameter needs both a name and a type, and the type comes after the name:
func welcomeUser(name string) {
fmt.Println("Welcome, " + name + "!")
}
Here name is the parameter and string is its type. Inside the body, name behaves like a local variable. The + operator joins strings, so the call builds the greeting from three pieces. Mind the space after the comma in "Welcome, ".
Arguments in a call
The values you write in the parentheses of a call are the arguments. Each argument is copied into the matching parameter for that call:
func mainFunction() {
welcomeUser("Andy") // Welcome, Andy!
}
During this call name holds "Andy". On the next call it can hold something else. The parameter is the name in the definition, and the argument is the value in the call.
Several parameters
List parameters in the header separated by commas, each with its type:
func printPerson(name string, age int) {
fmt.Println(name + ", aged " + strconv.Itoa(age))
}
Arguments are matched by position, so printPerson("John", 30) prints John, aged 30. The order of the arguments must follow the order of the parameters. strconv.Itoa turns an int into a string, because + won't join a string and a number. Neighbouring parameters of the same type can share one type: func add(a, b int) means both are int.
Variables as arguments
An argument can be any expression of the right type, including a variable:
func mainFunction() {
name := "Andy"
age := 28
printPerson(name, age) // Andy, aged 28
printPerson("Mary", age) // Mary, aged 28
}
The function receives the value stored in the variable. It gets a copy, so assigning to the parameter inside the function does not change the caller's variable. In a test, a function that appended ! to its parameter printed hey!, while the caller's variable still held hey afterwards.
The exercise, step by step
- Define
welcomeUserabovemainFunctionwith one parameter,name string, so the greeting can change with each call. - Print the greeting by concatenating
"Welcome, ",nameand"!". For"Andy"the output isWelcome, Andy!. - Call it with a literal. In
mainFunction, pass"Andy". That value becomes the parametername. - Create a variable with
name := "John". The short declaration infers the typestringand works only inside a function. - Pass the variable.
welcomeUser(name)sends the value"John", which shows that an argument doesn't have to be a literal.
The solution in Go
func welcomeUser(name string) {
fmt.Println("Welcome, " + name + "!")
}
func mainFunction() {
welcomeUser("Andy")
name := "John"
welcomeUser(name)
}
This prints:
Welcome, Andy!
Welcome, John!
The variable in mainFunction is also called name, but it is a different variable from the parameter. Each function has its own scope, so the two names could differ without any change in behaviour.
Common mistakes
- Leaving out the type. A parameter written as
namealone does not compile. - Putting the type first. Go writes
name string, notstring name. - Too few or too many arguments.
welcomeUser()fails withnot enough arguments in call to welcomeUser, and two arguments fail withtoo many arguments. - The wrong type of argument.
welcomeUser(42)is rejected withcannot use 42 (untyped int constant) as string value. - Swapped arguments.
printPerson(30, "John")fails to compile, since the types are in the wrong order. When both parameters have the same type, a swap compiles and gives wrong output. - Joining a string and an int with
+. The compiler reports mismatched types. Convert the number first.
Key takeaways
- A parameter is declared in the header with a name and a type, in that order.
- An argument is the value passed in a call, matched to parameters by position.
- Arguments can be literals, variables or other expressions of the right type.
- Go passes a copy of each argument, so changing a parameter doesn't change the caller's variable.